簡體   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