考虑执行此操作的UIViewController
子类(使用ARC):
- (void)viewDidLoad {
__weak id wself = self;
dispatch_async(backgroundQueue, ^{
longRunningOperation();
dispatch_async(mainQueue, ^{
[wself updateView];
});
});
}
问题
答案 0 :(得分:1)
如果您需要支持取消,则NSOperation/NSOperationQueue
更易于使用。
如果对象被释放,那么在大多数情况下它应该没有问题,因为在nil
上调用方法是noop。但是,如果您使用任何直接的ivar访问(self->myIvar
),那么您可能会遇到崩溃,因为您将取消引用nil
。解决这个问题的一种方法是在对对象执行任何操作之前获得强引用:
- (void)viewDidLoad
{
[super viewDidLoad];
__weak __typeof(self) weakSelf = self;
dispatch_async(backgroundQueue, ^{
longRunningOperation();
dispatch_async(mainQueue, ^{
__typeof(weakSelf) strongSelf = weakSelf;
strongSelf->myIvar;
});
});
}
答案 1 :(得分:0)
在此代码中使用wself可能允许在longRunningOperation仍在执行时取消分配视图控制器。在这种情况下,我不认为传递弱自我是必要的,因为没有机会进行涉及块的循环引用。
就中断执行而言,最好的办法是在ViewDidDisappear中设置一个标志,使视图不再可见,并在执行updateView之前检查该标志。
答案 2 :(得分:0)
检查this SO question,这里有一个很好的答案,详细描述了GCD缺少取消功能。
除此之外,如果你尝试执行这段代码并在块执行时检查wself
和self
的值(另外,在检查自己的时候注释掉自己),你会看到wself
变为nil
而self
仍有值..所以我认为你在这里避免直接引用self
是正确的。如果您同时检查同一个区块中的wself
和self
,则wself
仍会有值。因此,如果您在块中直接引用self
,则此块可以基本上保持wself
更长时间。因此,使用wself
将确保您不会无意中使事物保持活动的时间长于预期,因此选择器实际上不会做任何事情。
因此,您可以在执行时检查块中nil
是否已成为nil
,或者您可以依靠Objective-C在向{{1}传递消息时悄然无效(只要它不是一个无法识别的选择器)。
答案 3 :(得分:0)
如果您需要取消某些操作,请使用NSOperation和NSOperationQueue进行更好的编程。这将允许您取消应与视图一起取消分配的操作