views:

30

answers:

1

My app currently has what I'm pretty sure is a bad design, but I'm not sure how I can organize it any better. For example: LoginViewController sends the input text for the username and password to an instance of UserController. UserController sends a request to my server to validate the username and password, via NetworkRequestController which is responsible for dealing with all client-server communications. NetworkRequestController parses the server JSON responses and sends it back to a designated selector on the UserController, which then does all of it's business before informing the view of the result.

Currently, the UserController is instantiated as a local property to the LoginViewController during the LoginViewController's viewDidLoad method - though I feel I would prefer it to be a singleton class. The problem is that I need to set another object (such as LoginViewController) as the delegate on UserController in order to get the login result all the way back to the view with the appropriate selectors.

//LoginViewController sends request to local UserController instance
[userController validateLoginWithDelegate:self 
    withResult:@selector(loginResult:) 
    forEmail:email.text 
    forPassword:password.text];

//UserController asks NetworkRequestController to send login to server
- (void)validateLoginWithDelegate:(id)delegateObj
    withResult:(SEL)onResult
    forEmail:(NSString *)email 
    forPassword:(NSString *)password {

    if(delegateObj != nil && onResult != nil){
        self.delegate = delegateObj;
        self.resultSelector = onResult;
    }

    NSString *url = [NSString stringWithFormat:@"/UserService.cfc?method=Authenticate&email=%@&password=%@&returnFormat=JSON", email, password];

    [[NetworkRequestController sharedNetworkRequestController] 
        requestJSONWithURLString:url 
        andDelegate:self 
        onFinished:@selector(onLoginResult:) 
        onFailed:nil 
        onOffline:nil 
        progressView:nil 
        timeout:30];

}

//NetworkRequestController sends the request to the server and sends the parsed JSON back to UserController
[delegate performSelector:onFinished withObject:parsedJSON];

//UserController does it's business and sends the result to the view
if(delegate != nil && resultSelector != nil){
    [delegate performSelector:resultSelector withObject:result];
}

I've only been working with Obj-C and Cocoa a few months and I'm pretty sure this is almost considered good, but I'm more certain there's something I'm missing. Can this be achieved with protocols? Advice?

A: 

Delegates are intended for two way communication between objects that serve different roles. Usually one object knows how to do something and the other object, the delegate, knows what to do.

When you have one way communication, notifications are often a better choice. You do not need the formality of a delegate with one way communication.

The two can be used together. For example, UIApplication has a delegate but also sends notifications for many of the delegate calls.

If the UserController is a singleton, then any instance can make requests and it can broadcast a notification of the results to all interested objects.

[NSNotificationCenter defaultCenter] sends notifications within your application.

drawnonward