繁体   English   中英

如何正确通知委托人该实例不再需要?

[英]How to correctly notify a delegate that the instance is no longer needed?

这是我的模式:

1)SpecialView创建一个MessageView并对其进行强有力的引用。

2)用户在MessageView中点击一个按钮,使其淡出。 然后,MessageView告诉它的委托SpecialView,它完全消失了。

3)SpecialView发布MessageView。

问题是这样的:

- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
    [self.delegate messageViewFadedOut:self]; // delegate releases us...
    // self maybe got deallocated... BOOM!
    // now what? method of a zombie returns? stack freaks out?
} // does it even return?

在最后一行中,我将调用委托,委托将立即释放MessageView。 -fadedOut:finished:context:由核心动画didStopSelector回调调用。

我担心的是,MessageView实例将在-fadedOut:finished:context:完全返回之前立即被释放,从而导致非常讨厌的随机错误

很久很久以前,一位资深的资深程序员告诉我:“切勿割断您所坐的树枝。”

因此,为了确保实例在此方法返回之前一直存在,我在调用委托之前做了一次retain-autorlease-dance。

- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
    //[[self retain] autorelease];
    [self.delegate messageViewFadedOut:self]; // delegate releases us...
}

但是,在ARC下,不再允许保留-自动释放的舞蹈(迁移工具将不允许),并且似乎没有办法强制ARC系统执行类似的操作。

所以我想出了这个策略:

- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
    [self.delegate performSelector:@selector(messageViewFadedOut:) withObject:self afterDelay:0];
}

延迟的performSelector有望使方法完全返回。 据我所知,延迟为0仍保证选择器在下一个运行循环迭代中执行,而不是立即执行。

这很有可能也是伪造的。

我该如何正确地解决这个问题,即一个对象要求另一个对象销毁对它的最后一个引用,从而有可能在调用另一个对象的方法有机会完全返回之前将对象重新分配? 会有像堆栈跟踪僵尸这样的东西吗?

在ARC下如何解决类似问题?

坦白地说,我认为与其尝试模仿保留自动释放,还应确保在调用委托方法messageViewFadedOut:不要在意是否释放了对消息视图的拥有引用。 willFadeOut:方法的willFadeOut:可能会假设它不会被取消分配,但是fadedOut:didFadeOut:方法对于被取消分配的对象应该没问题。

一个理想的解决方案是,通过取消正在发生的任何活动淡入动画(将引用保留在某个地方), dealloc方法可以特别避免可怕的令人讨厌的错误。 这样一来,您就不必在乎如何或何时使用dealloc ,因为dealloc知道这样做X是为了防止在死时留下任何对象状态或视觉异常。

因此,只需使用您的解决方案( performSelector:withObject:afterDelay:或一个GCD块:

- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 250 * NSEC_PER_MSEC), // 250ms
                   dispatch_get_current_queue(),
                   ^{
                        [self.delegate messageViewFadedOut:self];
                   });
}

此外,ARC可能会立即autorelease ,为什么不多次测试该代码段并查看会发生什么呢? dealloc放置一个断点,看看在方法返回之前是否调用了该断点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM