Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSThread and UIViewController interaction

If I spawn a new thread, and then within it I push a new controller onto my UINavigationController, using code like this...

(a) not working

-(void)myCallbackInThread
{
    // move on...
    UIApplication* app = [UIApplication sharedApplication];
    [app changeView];
}

then I find that the view appears, but does not respond to user input.

If I change the code like this

(b) working

-(void)myCallbackInThread
{
    // move on...
    UIApplication* app = [UIApplication sharedApplication];
    [app performSelectorOnMainThread:@selector(moveToMain) withObject:nil waitUntilDone:FALSE];
}

Then everything works just fine.

Any hints as to why?

like image 256
Airsource Ltd Avatar asked Oct 03 '08 15:10

Airsource Ltd


2 Answers

In your case, it really depends on what's happening in [app changeView], but the reason it stops responding is most likely that you have no run loop dispatching events on your new, secondary thread (more on this below). In general, however, it is a very bad idea to update the GUI from a secondary thread. As you've already discovered, all of these events should go through the main thread.

The main reason that your second example works and not your first is that UIApplication sets up and handles the run loop and event dispatcher for you on the main thread. So, when you call performSelectorInMainThread, the selector gets dispatched to the main run loop which is able to then handle your gui input and other events. The event dispatcher is also run and managed by UIApplication on the main thread.

So basically, don't perform any GUI management activities on a secondary thread. Dispatch those to the main thread. And if you need processing on a secondary thread (for things like timers or asynch calls, etc.) then you have to start and manage your own run loop on that thread (see NSRunLoop for more on managing your on run loop).

like image 199
Jason Coco Avatar answered Oct 03 '22 15:10

Jason Coco


Just found this in the iPhone threading docs

If your application has a graphical user interface, it is recommended that you receive user-related events and initiate interface updates from your application’s main thread. This approach helps avoid synchronization issues associated with handling user events and drawing window content. Some frameworks, such as Cocoa, generally require this behavior, but it also has the advantage of simplifying the logic for managing your user interface.

I still don't see what would actually cause something to display but not be able to receive user input, but I'll follow that guideline in future.

like image 34
Airsource Ltd Avatar answered Oct 03 '22 14:10

Airsource Ltd