From Apple doc
Threads and Your User Interface
If your application has a graphical user interface, it is recommended that you receive
user-related events and initiate interface updatesfrom 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 even for those that do not, keeping this behavior on the
main thread hasthe advantage of simplifying the logic for managing
your user interface. There are a few notable exceptions where it is
advantageous to perform graphical operations from other threads. For
example, the QuickTime API includes a number of operationsthat can be
performed from secondary threads, including opening movie files,
rendering movie files, compressing movie files, and importing and
exporting images. Similarly, in Carbon and Cocoa you can use secondary
threads to create and process images and perform other image-related
calculations. Using secondary threads for these operations can greatly
increase performance. If you are not sure about a particular graphical
operation though, plan on doing it from your main thread
In addition, UI classes are not thread-safe according to the thread programming guide.
So, avoid to update the UI from a thread different from the main thread.
If you run an NSOperation
(within a queue) you could update your UI (for example after having download some data required for your app lifecycle) performing a method in the main thread like the following:
-(void)main {
// e.g the delegate could be the controller that has the view that you want to update
if (delegate) {
NSURL *url = [delegate urlForDownloadOperation:self];
if ( nil == url ) return;
self.downloadedImage = [[NSImage alloc] initWithContentsOfURL:url];
// e.g. rather than invoking processImage directly on the delegate, ensure that the method draw the image on the main thread
[delegate performSelectorOnMainThread:@selector(processImage:)
withObject:self waitUntilDone:YES];
}
}
Or you could send a notification to the component that need to update the UI like:
- (void)main {
NSURL *url = [delegate urlForDownloadOperation:self];
if ( nil == url ) return;
self.downloadedImage = [[NSImage alloc] initWithContentsOfURL:url];
// e.g. send a notificatio to inform some components that it is ready to update the UI with some content
[[NSNotificationCenter defaultCenter] postNotificationName:@"importData" object:self];
}
The component that needs to update the UI will register for that notification like
- (void)processImage:(NSNotification*)notification
{
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(processImage:) withObject:notification waitUntilDone:YES];
return;
}
// update the UI here, you are running on the main thread
}