views:

527

answers:

2

I'm using AsyncSocket to connect to a server from my iPhone App. In the delegate that received data from the server, I post a notification that would tell the tableView's delegate to trigger a reloadData on the tableView:

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData*)data withTag:(long)tag {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"PEERSTATUSCHANGED" object:self];
    [sock readDataToData:[AsyncSocket CRLFData] withTimeout:-1 tag:0];
}

and on the viewController:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(peerStatusDidChange:) name:@"PEERSTATUSCHANGED" object:nil];
    }
    return self;
}


- (void)peerStatusDidChange:(NSNotification *)notification {
    NSLog(@"NOTIFICATION RECEIVED");
}

Now, this doesn't work at all. The notification is posed but not recognized by the ViewController. However, when I do the same thing in applicationDidFinishLaunching:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

protocol = [[XBBProtocol alloc] init];

SourceListViewController *sourceListVC = [[[SourceListViewController alloc] initWithNibName:@"SourceListViewController" bundle:nil] autorelease];
UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:sourceListVC] autorelease];

[[NSNotificationCenter defaultCenter] postNotificationName:@"PEERSTATUSCHANGED" object:self];
[protocol connectToServer];

// Override point for customization after application launch
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}

I got the notification received in viewController.

Anyone knows why? does it have something to do with delegate methods of AsyncSocket being in different thread?

Thanks in advance.

+1  A: 

One possibility is that your initWithNibName:bundle: method is not actually being called. If you instantiate the view controller in a NIB (rather than in code), then it calls initWithCoder: instead.

A quick way to check is to put a breakpoint in initWithNibName:bundle:.

Daniel Dickison
I did put a breakpoint in the initWithNibName:bundle: method, and the notification registration did indeed run. Also, the viewController did receive the notification posted in the applicationDidFinishLaunching method. really weird. So you're saying that AsyncSocket shouldn't affect how nsnotification works?
Ben
AsyncSocket shouldn't affect notifications. How about onSocket:didReadData:? Are you sure that method is getting called? It's possible you never start the initial read...
Daniel Dickison
+1  A: 

Try putting the method that sends the notification in a different method, and call it with "performSelectorOnMainThread". It's very likely your network code is getting called in a background thread and thus when the notification fires, it informs the table view on the same thread...

You can't make UI calls on anything but the main thread.

Kendall Helmstetter Gelner
AsyncSocket schedules its network operations on the run loop of the thread from which its read/write methods were called. And, notifications are sent on the thread they're posted in, so unless a thread was explicitly detached the notification methods should be happening on the main thread.
Daniel Dickison
But if reloadData is being called and not working when it does work from the app delegate, it's almost certain somewhere he's using a background thread.
Kendall Helmstetter Gelner