Reputation: 249
Anything UI related work needs to be run on main thread for iOS. Sometimes we need to do some async job like downloading a image and we probably would use dispatch_async and when the download finishes we get the main thread and display it like something like this:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *overlayImage = [self faceOverlayImageFromImage:_image];
dispatch_async(dispatch_get_main_queue(), ^{
[self fadeInNewImage:overlayImage];
});
});}
But when we load an image locally we usually just do this without dispatching on main thread:
UIImageView *imageView = [[UIImageView alloc] initWithImage:@"myimage.png"];
My question is are they guaranteed to be run on main thread? If yes why should we dispatch it using dispatch_get_main_queue()? If no why don't we need to dispatch every ui related work on main thread?
Upvotes: 2
Views: 1740
Reputation: 131418
You're confused.
A given call chain is either run on the main thread or on a background thread. Most of the code you deal with is invoked through system events, and is guaranteed to be run on the main thread. There are only a limited number of cases where your code will be invoked from a background thread. Only in those cases do you need to wrap UIKit calls in code that redirects the call to the main thread.
The most common reason for your code to be running from a background thread is because you invoked it that way - often using Grand Central Dispatch.
You might invoke some code like this:
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
//This code will be on a background thread
//Do time-consuming work here
//This calls back to the main thread.
DispatchQueue.main.async { [weak self] in
//Put your code to display your results in the UI here.
}
}
View controller functions, button actions, etc are always called on the main thread. If the system calls some method on a background thread, it will be well documented.
Some functions that take completion handlers invoke those completion handlers on a background thread. The NSURLSession
(URLSession
) class, for example, invokes its completion handlers and delegate methods on a delegate queue that defaults to a background thread. So when you pass a completion handler to an instance of URLSession
, you need to make sure your UIKit code is wrapped in a call to dispatch_async()
(DispatchQueue.main.async()
in Swift 3) or a similar method of passing code to the main thread to execute.
Upvotes: 8
Reputation: 318814
Most UI related actions need to be performed on the main thread for them to work properly. But simply using a UI...
class does nothing itself to ensure it is run on the main thread.
That's your job as the programmer. If you do something (like download data or perform a long running task) in the background and then need to update the UI, you must ensure the UI code is done on the main thread.
Keep in mind that creating UIImage
instances can safely be created on a background thread. That's safe.
tl;dr - no, nothing is guaranteed to be run on the main thread. And you do need to dispatch every UI related work on the main thread unless you are already on the main thread.
Upvotes: 3