2011-09-03 59 views
198

在我的小iPad應用程序中,我有一個使用觀察者的「切換語言」功能。每個視圖控制器在其viewDidLoad:期間向我的觀察者註冊自己。自定義dealloc和ARC(Objective-C)

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [observer registerObject:self]; 
} 

當用戶點擊「更改語言」按鈕,新的語言被保存在我的模型和觀察者通知,並呼籲其註冊的對象的updateUi:選擇。

這工作得很好,除了當我有一個TabBarController視圖控制器。這是因爲當標籤欄加載時,它從其子控制器中提取標籤圖標而不初始化視圖,因此viewDidLoad:未被調用,所以這些視圖控制器不會收到語言更改通知。因此,我將registerObject:調用轉移到了init方法中。

當我用viewDidLoad:向我的觀察者註冊時,我用viewDidUnload:取消註冊。由於我現在正在註冊init,因此在dealloc註銷很有意義。

但這是我的問題。當我寫:

- (void) dealloc 
{ 
    [observer unregisterObject:self]; 
    [super dealloc]; 
} 

我得到這個錯誤:

​​

因爲我需要調用[super dealloc]確保超收拾妥當,但ARC禁止的是,現在我卡住了。有什麼方法可以在我的物體快要死亡時獲得消息?

+0

作爲一個側面說明 - 像這樣的情況可能會導致內存泄漏,這將不會顯示在泄漏工具中。如果dataModel保留對觀察者的引用(這是ARC下的默認事件,即使對於ivars),dealloc將永遠不會被調用,因爲保留計數將大於零。所以,你可能需要手動取消註冊觀察者才能首先調用dealloc。 –

+0

我爲左手和右手選項實現了類似的功能。唯一需要該消息的VC是當前顯示的一個。其他人在viewDidLoad或viewDidAppear中查看模型以更改界面。也許這樣的事情會更好。 –

+0

@BlazejCzapp因爲他使用的是UITabBarController,我們假設UITabBarController將始終持有對已註冊控制器的引用(因爲我猜是它的'子'控制器),內存泄漏仍然是一個問題?我不知道註冊控制器何時會被分配。謝謝 – Objectif

回答

400

當使用ARC,你根本不叫[super dealloc]明確 - 編譯器會爲您整理(如Clang LLVM ARC document, chapter 7.1.2描述):

- (void) dealloc 
{ 
    [observer unregisterObject:self]; 
    // [super dealloc]; //(provided by the compiler) 
} 
+2

如果視圖持有對觀察者的引用,並且觀察者持有該視圖的引用,那麼我們有一個循環引用。所以視圖的引用計數大於0,並且'dealloc'永遠不會被調用。在dealloc中調用''[observer unregisterObject:self]'是否合理?我錯過了什麼? – user443854

+0

多數民衆贊成在工作。導致觀察者本身持有對控制器的引用。這將首先防止被調用的dealloc – hasan83

相關問題