2

I am developing an app based on the Master-View template provided by Apple (it consists of two ViewControllers, the MasterViewController and the DetailViewController). I have added a Model for communication with my server.

However, when my Model receives a message from the server, it needs to call a method in the MasterViewController or DetailViewController class. How can I do this?

All help is greatly appreciated.

danielmhanover
  • 3,094
  • 4
  • 35
  • 51

4 Answers4

3

You could fire notifications from the model, which are handled by the Master and Detail View controllers.

In the model:

- (void)receivedMessageFromServer {
    // Fire the notification
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ReceivedData" 
                                                        object:nil];   
}

Handle the "ReceivedData" notification in your View Controller(s):

- (void)viewDidLoad {
    [NSNotificationCenter defaultCenter] addObserver:self 
                                            selector:@selector(receivedDataNotification:) 
                                                name:@"ReceivedData" 
                                              object:nil];
}

- (void)receivedDataNotification:(id)object {
    NSLog(@"Received Data!");
}
melsam
  • 4,947
  • 1
  • 22
  • 23
  • But how do I send a string through NSNotifications? it seems all I am able to do is send an empty notification – danielmhanover May 27 '12 at 22:17
  • 2
    use the object parameter. I'm passing it nil in the example above, but you can pass in any object like you, including NSStrings. – melsam May 27 '12 at 22:52
  • question :) - should I use notification or delegate? I saw in the answers that delegate is suggested too. Which way is better? – trillions Mar 09 '13 at 19:57
  • notification is better, because in this way the MVC conversation rules are not violated. Model just broadcasts a notification and the view controller just chooses to receive it, as supposed to delegate where you would actually let the Model weakly get ahold of the view controller, which is a bad design. View controllers should talk to Models actively, not the other way around. – Frank Li Aug 23 '15 at 05:29
3

Actually the MVC pattern that Apple proposes allows for notifications from the model to the controller.

A good way to achieve this goal could be to deliver NSNotification objects through the NSNotificationCenter when your data changes, with information on what is changed, and let the listeners take care of it.

diegoreymendez
  • 1,997
  • 18
  • 20
  • But how do I send a string through NSNotifications? it seems all I am able to do is send an empty notification – danielmhanover May 27 '12 at 22:21
  • 1
    Please refer to [Apple's documentation on NSNotificationCenter](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html). You can assign a name and a sender object to your notification with `- (void)postNotificationName:(NSString *)notificationName object:(id)notificationSender`. – diegoreymendez May 27 '12 at 22:37
  • For example you could have the data object be the sender, and the notification name could be a string such as: `@"senderNamePropertyChanged"` (I recommend that you use constants to define allowed notification names). – diegoreymendez May 27 '12 at 22:39
  • I realized I can use the optional UserInfo argument. – danielmhanover May 27 '12 at 22:40
2

You should use the optional protocol delegate method. I have an answer with example how to setup delegate method in this PO.

Community
  • 1
  • 1
user523234
  • 14,323
  • 10
  • 62
  • 102
1

Blocks are the way to go.

You need to have a reference to your model in ViewController. When you want to update data you send a message to the model and pass block as a parameter to it which would get called when the response is received from server.

For example:

View Controller

[self.model fetchDataFromRemoteWithCompletionHandler:^(id responseObject, NSError *error)
{
    // responseObject is the Server Response
    // error - Any Network error
}];

Model

-(void)fetchDataFromRemoteWithCompletionHandler:(void(^)(id, NSError*))onComplete
{
    // Make Network Calls
    // Process Response
    // Return data back through block
    onComplete(foobarResponse, error);
}
GoodSp33d
  • 6,252
  • 4
  • 35
  • 67