从后台线程调用dealloc
上的UIViewController
是错误的吗?似乎UITextView
(可以?)最终调用_WebTryThreadLock
会导致:
bool _WebTryThreadLock(bool):试图从线程获取Web锁 除主线程或网络线程之外。这可能是打电话的结果 从辅助线程到UIKit。
背景:我有一个子类NSOperation
,需要selector
和target
个对象通知。
-(id)initWithTarget:(id)target {
if (self = [super init]) {
_target = [target retain];
}
return self;
}
-(void)dealloc {
[_target release];
[super dealloc];
}
如果在UIViewController
开始运行时NSOperation
已被解除,则对release
的调用会在后台线程上触发dealloc
。
答案 0 :(得分:9)
是的,在后台线程(或队列)中释放UIViewController是一个错误。在UIKit中,dealloc不是线程安全的。这在Apple的TN2109 doc:
中有明确说明当辅助线程保留目标对象时,必须确保线程在主线程释放其对象的最后一个引用之前释放该引用。如果不这样做,则辅助线程将释放对象的最后一个引用,这意味着对象的-dealloc方法在该辅助线程上运行。如果对象的-dealloc方法执行在辅助线程上不安全的事情,这是有问题的,这对UIKit对象(如视图控制器)来说很常见。
答案 1 :(得分:6)
简单的规则是从后台线程UI*
上执行任何是错误的。
答案 2 :(得分:3)
这里的第二篇文章提供了有用的信息,但他们的答案对我不起作用。
UIWebView in multithread ViewController
似乎这可能已在iPhone OS 4中得到解决,但不确定。
当[NSThread isMainThread]为NO时,我最终没有在控制器的dealloc中释放我的UIWebView。宁愿泄漏而不是崩溃(直到我得到更好的解决方案)。
答案 3 :(得分:2)
在任何时候调用dealloc都是错误的。你应该只打电话给释放。
您不应该从后台线程访问任何UI相关实例。这包括使用getter方法,因为它们可能会在内部修改内容。但是,只要遵循保留和释放的常规规则,保留和释放在任何时候都对任何对象都是线程安全的。 UI相关实例包括活动UIView或UIViewController引用的任何对象。
performSelectorOnMainThread除了保留对象直到它到达主线程之外什么都不做。调用任何与UI相关的对象是安全的。