I need to perform an asynchronous function execution because it is blocking the main thread and hence the UI is not available.
After looking at the questions in stackoverflow, I know there are three ways to do asynchronous function.
An example:
[NSThread detachNewThreadSelector:@selector(showSpinner:) toTarget:self withObject:self.view];
// or
[self performSelectorInBackground:@selector(showSpinner:) withObject:self.view];
// or
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(showSpinner:) object:self.view];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:invOperation];
// or
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self showSpinner:self.view];
});
});
My question is how does performSelectorInBackground
and detachNewThreadSelector
return back to main thread? how do you know that they are done?
A couple of thoughts:
You might want to check Migrating Away From Threads in the Concurrency Programming Guide, which makes a compelling argument for dispatch queues and operation queues, which are discussed earlier in that same guide.
Also, as you delve into various asynchronous operations, remember, do time consuming stuff in background queues/threads, but always dispatch UI stuff back to the main queue. I only mention that because your task, showSpinner
sounds a lot like a UI task, which you would never want to do in a background queue/thread. If it has some "expensive" non-UI related tasks, then fine, do that in the background, but make sure the UI stuff gets dispatched back to the main queue.
There are, as an aside, other renditions of the operations queues, e.g., block operations:
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperationWithBlock:^{
// do some slow stuff in the background here
// ok, now do UI stuff in the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self showSpinner:self.view];
}];
}];
This is roughly equivalent to the GCD (dispatch queue) rendition:
dispatch_queue_t dispatchQueue = dispatch_queue_create("com.ramshad.app", 0);
dispatch_async(dispatchQueue, ^{
// do some slow stuff in the background here
// ok, now do UI stuff in the main queue
dispatch_async(dispatch_get_main_queue(), ^{
[self showSpinner:self.view];
});
});
There are tons of subtle pros and cons between the operation queues and dispatch queues (which we should not get into here because it's been discussed hundreds of times elsewhere on Stack Overflow), but both let you do surprisingly rich asynchronous operations with less complexity than traditional thread programming.
If you decide to stick with threads versus operation and/or dispatch queues (which I wouldn't necessarily recommend), you might want to check out the Threading Programming Guide.
To identify performSelectorInBackground
& detachNewThreadSelector
end of execution,call a method at the end of the thread method on main thread.
Additionaly NSThread
provides an propery as isFinished
which returns a Boolean value that indicates whether the receiver has finished execution.
Example:
[self performSelectorOnMainThread:@selector(threadMethod)
withObject:nil
waitUntilDone:NO];
or
[NSThread detachNewThreadSelector:@selector(threadMethod)
toTarget:self
withObject:nil];
-(void)threadMethod{
//here your implementation code
//here call the end notification method.
[self performSelectorOnMainThread:@selector(ThreadExecutionDone)
withObject:nil
waitUntilDone:YES];
}
-(void)ThreadExecutionDone{
//end of the performSelectorInBackground or detachNewThreadSelector.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With