How to pass information from appDelegate into one

2019-04-12 15:25发布

问题:

In the iphone app that I'm working on I use a custom class to manage network communication with the host. The class called protocolClass is an ivar in the appDelegate and alloc + init in the applicationDidFinishLaunching: method.

Now whenever the protocolClass receive data from the host, it calls protocolClassDidReceiveData: method in its delegate (which I set as the appDelegate). I need then to update the data in one of the customViewControllers in the UINavigatorController.

Should I just add a reference to the customViewController I need to update in the appDelegate? or is there some other more efficient method?

If I were to keep a reference to the customViewcontroller, what are the memory usage ramifications?

Thanks in advance.

回答1:

If I get you right, you want to update a view after an event occurs in some unrelated part of your program.

To reduce the number of dependencies in your code, I'd recommend to use an NSNotification instead of the more tightly coupled instance variable. Notifications are a Cocoa concept, which allows one part of your code to emit an event-like message that any number of listeners can register for.

In your case it would look like this:

AppDelegate header:

extern NSString* kDataReceived;

AppDelegate implementation:

NSString* kDataReceived = @"DataReceived";

- (void)protocolClassDidReceiveData:(NSData*)data {
    [[NSNotificationCenter defaultCenter] postNotificationName:kDataReceived
                                                        object:self
                                                      userInfo:data];
}

in the implementation of some interested listener class (e.g. your UIViewController):

// register for the notification somewhere
- (id)init
{
    self = [super init];
    if (self != nil) {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(dataReceivedNotification:)
                                                     name:kDataReceived
                                                   object:nil];
    }
}

// unregister
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

// receive the notification
- (void)dataReceivedNotification:(NSNotification*)notification
{
    NSData* data = [notification userInfo];
    // do something with data
}


回答2:

Yes, Notifications are a good way to do it. And when a Model wants to update the Controller [i.e. ViewController] - notification is a good way of doing it. In my case I am trying to discover devices using SSDP (using the AsyncUdpSocket), and I wanted to update/notify my view controller when I found the device. Since this is asynchronous, when the data is received, I used notification. Here is the simple thing I did:

In the viewDidLoad (I tried overriding the init but that did not work well for me) - I registered my ViewController for a notification as follows:

*NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self
           selector:@selector(foundController:) 
               name:@"DiscoveredController"
             object:nil];

Here is the selector in my ViewController:

// receive the notification
- (void)foundController:(NSNotification *)note
{
    self.controllerFoundStatus.text = @"We found a controller";
}

In my "Model" [Not the App Delegate - I have created a new Class that I use to discover the devices "serviceSSDP" all I did was to post the notification as follows:

[[NSNotificationCenter defaultCenter] postNotificationName:@"DiscoveredController" object:nil];

That's it. This posting of notification is in when I get the correct response to my SSDP discovery [specifically in the:

- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock 
     didReceiveData:(NSData *)data 
            withTag:(long)tag 
           fromHost:(NSString *)host 
               port:(UInt16)port

of the AsyncUdpSocket.