我需要执行异步函数执行,因为它阻塞了主线程,因此UI不可用。
在查看stackoverflow中的问题后,我知道有三种方法可以执行异步功能。
一个例子:
[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];
});
});
我的问题是performSelectorInBackground
和detachNewThreadSelector
如何返回主线程?你怎么知道他们已经完成了?
答案 0 :(得分:7)
有几点想法:
您可能需要检查并发编程指南中的Migrating Away From Threads,它为调度队列和操作队列提供了一个引人注目的参数,这在前面的同一指南中有所讨论。
此外,当您深入研究各种异步操作时,请记住,在后台队列/线程中耗费时间,但始终将UI内容分配回主队列。我只提到,因为你的任务,showSpinner
听起来很像UI任务,你在后台队列/线程中永远不会想做。如果它有一些昂贵的"非UI相关的任务,然后很好,在后台执行,但确保将UI内容分派回主队列。
除此之外,还有其他操作队列的再现,例如块操作:
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];
}];
}];
这大致相当于GCD(调度队列)再现:
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];
});
});
操作队列和调度队列之间存在大量的微妙优点和缺点(我们不应该在这里讨论,因为它已经在Stack Overflow上的其他地方被讨论了数百次),但是两者都让你做得非常丰富异步操作的复杂性低于传统的线程编程。
如果您决定坚持使用线程与操作和/或调度队列(我不一定会推荐),您可能需要查看Threading Programming Guide。
< / LI> 醇>答案 1 :(得分:2)
识别performSelectorInBackground
&amp; detachNewThreadSelector
执行结束,在主线程上的线程方法结束时调用方法。
另外 NSThread
提供的属性为 isFinished
,返回一个布尔值,指示接收方是否已完成执行。
示例:强>
[self performSelectorOnMainThread:@selector(threadMethod)
withObject:nil
waitUntilDone:NO];
或强>
[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.
}