说我有课:
@interface MyClass : NSObject
@property(strong, nonatomic, readwrite) Widget* widget;
-(void)handleData:(NSData*)data;
-(void)foo;
@end
@implementation MyClass
-(void)handleData:(NSData*)data {
//...do a bunch of handleData then...
dispatch_async(dispatch_get_main_queue(), ^{
[_widget someMethodWithData:data];
});
}
-(void)foo {
//...do a bunch of foo then...
_widget = nil;
}
@end
据我所知,在dispatch_async
区块中,由于self
iVar,_widget
被保留。因此,假设正在处理主线程上的块时,其他一些非主线程调用foo
。突然之间,我的阻止了_widget
引用从它下面撕掉了,我得到了一些EXC_BAD_ACCESS (SIGSEGV)
。
乍一看,我想我会说:
Widget* localWidget = _widget;
dispatch_async(dispatch_get_main_queue(), ^{
[localWidget someMethodWithData:data];
});
但是,如果我需要制作本地的许多iVar,这种模式会变得很麻烦。
我想知道如果不编写一堆样板代码,我可以做些什么来避免这种情况?
答案 0 :(得分:1)
同时从两个单独的线程访问实例变量是不安全的。您需要某种同步机制,例如属性或@synchronized
块。例如:
@property(strong, readwrite) Widget* widget;
(注意缺乏非原子。)
通过属性访问该值:
@implementation MyClass
-(void)handleData:(NSData*)data {
//...do a bunch of handleData then...
dispatch_async(dispatch_get_main_queue(), ^{
[self.widget someMethodWithData:data];
});
}
-(void)foo {
//...do a bunch of foo then...
self.widget = nil;
}
@end
当然,如果异步调用foo,你的self.widget可能会返回nil。如果这不是您想要的行为,那么建议的局部变量解决方案就是您的选择。