我可以在-dealloc中调用[self retain]吗?或者,我如何确保主线程上发生dealloc?

Kev*_*ner 4 objective-c thread-safety dealloc ios objective-c-blocks

这是我的情况.这很复杂所以请耐心等待.

我有一个视图类,让我们称之为MyView.它会创建一个加载指示器子视图,然后启动一个将加载数据的后台操作.它还会创建一个块,后台队列操作在完成后将在主队列中排队.该块通过添加UITextView带有加载数据的另一个子视图a来准备视图.当然,要做到这一点,块必须具有对视图的引用.

因此后台操作保留了块,块保留了视图.和我一起到目前为止?

有时,MyView在后台队列操作完成之前,会从其超级视图中删除实例.有时,在后台队列操作被完全清除之前,主要的队列操作(调用块)会被彻底清除.在这种情况下,MyView可以-dealloc在后台线程上调用它的实例,因为对视图的最后一个引用属于该块,并且对该块的最后一个引用属于后台操​​作.

UIKit不喜欢从任何线程调用,而是主线程.在这种情况下UITextView,显然甚至包括-dealloc电话.我在文本视图中得到EXC_BAD_ACCESS了一个叫做"web thread lock"的东西-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
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当您调用-release一个对象时,如果保留计数达到零,则NSObject调用实现-dealloc.这一切都发生了吗?换句话说,是否可以接听电话-dealloc不是来电super?我制作某种可恶的僵尸物品还是这样好吗?

如果这不行,那么确保-dealloc在主线程上调用的好方法是什么?

une*_*lue 5

为什么不覆盖释放?

- (void)release
{
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
    } else {
        [super release];
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是预ARC.不要用ARC做.

  • 不,它仍然非常疯狂.您将在实施中产生排序和线程依赖关系,这将成为未来的噩梦.如果一个班级有如此繁重的拆除要求,那么拆除应该非常明确; 应该有一个`terminate`或`invalidate`或`doneWithYou`方法,该方法被非常明确地调用,并且非常明确地将该对象标记为无效.`release`或`dealloc`是错误的地方. (11认同)
  • 这实际上并不安全.`-performSelectorOnMainThread:...`机制本身需要保留和释放接收器.因此,这种方法可以导致无限递归或类似的事情.仅仅因为你尝试了它,并且在一些有限的情况下,它运行良好并不意味着它不会发生在其他情况或操作系统的未来版本中. (3认同)