2010-04-30 109 views
4

从后台线程调用deallocUIViewController上是错误的吗?似乎UITextView(可以吗?)最终调用_WebTryThreadLock这会导致:dealloc在后台线程

布尔_WebTryThreadLock(布尔):试图从一个线程 比主线程或web线程以外获得网络锁定。这可能是从辅助线程调用 到UIKit的结果。

背景:我有一个子类NSOperation,需要一个selectortarget对象来通知。

-(id)initWithTarget:(id)target { 
    if (self = [super init]) { 
     _target = [target retain]; 
    } 
    return self; 
} 

-(void)dealloc { 
    [_target release]; 
    [super dealloc]; 
} 

如果UIViewControllerNSOperation得到各地的跑步已经被开除,然后调用release触发它的dealloc在后台线程。

+0

[我的解决方案(使用NSTimer强制最后一个发布到主线程上)](http:// stackoverflow。com/questions/6353471/block-release-deallocating-ui-objects-on-a-background-thread/6482941#6482941“My solution”) – Jeff 2011-06-26 08:44:54

回答

7

是的,在后台线程(或队列)中释放UIViewController是错误的。在UIKit中,dealloc不是线程安全的。这是在苹果的TN2109文档明确描述:

当辅助线程保留目标对象,你必须确保线程释放主线程之前参考释放它的最后一个引用的对象。如果不这样做,则最后一个对象的引用由辅助线程释放,这意味着该对象的-dealloc方法在该辅助线程上运行。如果对象的-dealloc方法在辅助线程上执行的操作不安全,这对于UIKit对象(如视图控制器)来说很常见,这是有问题的。

+1

4年后,出现正确答案!不错的工作 - TN在我的问题后几个月发布,所以看起来我并不是唯一一个被这种行为困惑的人。 – 2014-06-25 14:21:21

6

简单的规则是从后台线程UI*是一个错误。

+0

'performSelectorOnMainThread'怎么样?这是记录在任何地方?我所看到的只是对“不要在后台线程中操作UI”的模糊引用 - 这比你的*任何*限制性要少得多。 – 2010-05-02 16:47:27

+2

这是调用performSelectorOnMainThread的常用方法:如果你想从后台线程操作UI。 – schaechtele 2010-05-03 14:42:38

+0

@schaechtele - 当你从一个不同的对象进行跨线程调用时,你是在调用[UIViewController performSelectorOnMainThread:]还是[self performSelectorOnMainThread:]? – 2010-05-03 18:55:29

3

这里的第二篇文章有一些有用的信息,但他们的回答对我来说并不适用。

UIWebView in multithread ViewController

这也似乎是,这可能在iPhone OS 4已经得到解决,但不能肯定。

当[N​​SThread isMainThread]为NO时,我最终没有在控制器的dealloc中释放我的UIWebView。宁愿泄漏比崩溃(直到我得到一个更好的解决方案)。

+0

是的 - 同样的问题。我通过在主线程中释放来解决这个问题,但我认为,对于sutorekease也同样适用。 我主要关心的是它是否是预期的行为,在ObjC中。我应该检查iPhone 4,看看它是否发生了变化 - 至少可以说明这是一个错误。 – 2010-05-26 22:10:35

+0

我认为这是iOS4的“固定”,至少基于粗略测试 – Jason 2010-06-12 15:45:24

2

在任何时候调用dealloc都是错误的。你只应该打电话发布。

您不应该从后台线程访问任何与UI相关的实例。这包括使用getter方法,因为它们可能会在内部修改内容。但是,只要遵循正常的保留和释放规则,保留和释放对任何对象都是线程安全的。与UI相关的实例包括由活动UIView或UIViewController引用的任何对象。

performSelectorOnMainThread除了保留一个对象直到它到达主线程之外不会做任何事情。调用任何与UI相关的对象是安全的。

+0

没错。我只调用release,但是因为它是最后一个版本,所以最终在内部调用dealloc。如果release是线程不可知的,那么dealloc必须是正确的 - 对吗?那么,_WebTryThreadLock只是规则的一个例外(可能是越野车)? – 2010-05-26 22:07:55