这是我的情况。这很复杂所以请耐心等待。
我有一个视图类,我们称之为MyView
。它会创建一个加载指示器子视图,然后启动一个将加载数据的后台操作。它还会创建一个块,后台队列操作在完成后将在主队列中排队。该块通过添加另一个子视图UITextView
来准备视图,其中包含已加载的数据。当然,要做到这一点,块必须引用视图。
因此后台操作会保留块,并且块保留视图。和我一起到目前为止?
有时在后台队列操作完成之前,会从其超级视图中删除MyView
的实例。有时,在后台队列操作被完全清除之前,主要的队列操作(调用块)会被彻底清除。在这种情况下,MyView
的实例可以在后台线程上进行-dealloc
调用,因为对视图的最后一个引用属于该块,并且该块的最后一个引用属于后台操作
UIKit不喜欢从任何线程调用,而是主线程。在UITextView
的情况下,显然甚至包括-dealloc
次来电。在文本视图的EXC_BAD_ACCESS
期间,我从称为“网络线程锁”的内容中获取-dealloc
。
我认为后台线程有时会有最后一个引用是合理的,我想在我的-dealloc
实现中处理这个问题,如下所示:
- (void)dealloc {
if ([NSOperationQueue currentQueue] == [NSOperationQueue mainQueue]) {
// The usual -- dealloc subviews safely on the main thread
self.myIvar = nil;
[super dealloc];
}
else {
// Not on the main thread, so keep the object alive
// in spite of the dealloc call.
[self retain]; // explicit retain
[[NSOperationQueue mainQueue]
addOperationWithBlock:^{ // implicit retain at block creation
[self release]; // explicit release
}]; // implicit release, dealloc called again, but on the main thread
}
}
因此,当您在某个对象上调用-release
时,NSObject
中的实现会在保留计数达到零时调用-dealloc
。这一切都发生了吗?换句话说,是否可以拨打-dealloc
和而不是来拨打super
?我制作某种令人讨厌的僵尸物品还是这样吗?
如果这不行,那么确保在主线程上调用-dealloc
的好方法是什么?
答案 0 :(得分:5)
- (void)release
{
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
} else {
[super release];
}
}
编辑:这是预ARC。请勿使用ARC。
答案 1 :(得分:1)
我见过这种方法:
- (void)dealloc {
if (is on main thread) {
[self _reallyDealloc];
} else {
[self performSelectorOnMainThread:@selector(_reallyDealloc)];
}
}
- (void)_reallyDealloc {
[ivar release];
[super dealloc]
}
这仍然不理想(并在ARC中断)。最好的答案是保证最终版本发生在主线程上。
原谅伪代码。在iPhone上键入代码是次优的
答案 2 :(得分:1)
为什么不避免将视图传递给在后台线程上执行的块?您可以让控制器注册通知,并让阻止在主线程的通知中心发出通知:
NSNotification *notification = [NSNotificationnotificationWithName:@"data upated" object:nil];
[[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];
答案 3 :(得分:1)
一旦调用dealloc,就太晚了。无论你做什么,该对象都会消失。如果问题是dealloc做了在后台线程上不安全的事情,那么dealloc可以将这些东西发送到主队列,当“self”早已消失时它们将被执行。
重写“保留”是完全变态的。让我们说当你在stack overflow.com上寻求建议时,你不应该做些什么。然后就是ARC,无论如何你都无法做到这一点。