Possible Duplicate:
Grand Central Dispatch (GCD) vs. performSelector - need a better explanation
To execute "stuff" on the main thread, should I use dispatch_async
or performSelectorOnMainThread
? Is there a preferred way, right/or wrong, and/or best practice?
Example: I'm performing some logic within the block of an NSURLConnection sendAsynchronousRequest:urlRequest
method. Because I'm doing stuff to the main view such as presenting a UIAlertView
I need to show the UIAlertView
on the main thread. To do this I'm using the following code.
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// code snipped out to keep this question short
if(![NSThread isMainThread])
{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
});
}
}];
Within that same if(![NSThread isMainThread])
statement I also call some custom methods. The question is, should I use the dispatch_async
method that I'm using above or is it better to use performSelectorOnMainThread
instead? For example, full code below:
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// code snipped out to keep this question short
if(![NSThread isMainThread])
{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
// call custom methods in dispatch_async?
[self hideLoginSpinner];
});
// or call them here using performSelectorOnMainThread???
[self performSelectorOnMainThread:@selector(hideLoginSpinner) withObject:nil waitUntilDone:NO];
}
}];
FYI - If I DO NOT perform these actions on he main thread I see a few second delay when presenting the UIAlertView
and I receive the following message in the debugger wait_fences: failed to receive reply: 10004003
. I've learned that this is because you need to make changes to the UI on the main thread... In case someone is wondering why I'm doing what I'm doing...
As mentioned in the links provided by Josh Caswell, the two are almost equivalent. The most notable differences is that performSelectorOnMainThread
will only execute in the default run loop mode and will wait if the run loop is running in a tracking or other mode. However, there are some significant differences for writing and maintaining the code.
dispatch_async
has the big advantage that the compiler does all its usual tests. If you mistype the method in performSelectorOnMainThread
you fail at run time, rather than compile time.dispatch_async
makes it much easier to return data from the main thread using the __block
qualifier.dispatch_async
makes it much easier to handle primitive arguments since you don't have to wrap them in an object. However, this comes with a potential pitfall. If you have a pointer to some data remember that block capture does not deep copy the data. On the other hand wrapping the data in an object as you would be forced to do for performSelectorOnMainThread
does deep copy (unless you set special options). Without a deep copy you can run into intermittent bugs that are frustrating to debug. So this means you should wrap things like char *
in NSString
before you call dispatch_async
.