1

我遇到了NSWindowController的一個奇怪的情況。我想要釋放窗口控制器,但它不會。它似乎不符合我對ARC行爲的期望。NSWindowController子類不會在ARC中發佈

我創建了一個簡單的窗口控制器的子類,PlainWindowController。它的接口和實現都是空的:

#import <Cocoa/Cocoa.h> 

@interface PlainWindowController : NSWindowController 
@end 

@implementation PlainWindowController 
@end 

我用它創建一個默認windowController廈門國際銀行名爲PlainWindowController.xib,它與代表和windowController連接的窗口已經設置。當這個測試運行中,弱引用不是nil

PlainWindowController *strongWindowController = [[PlainWindowController alloc] initWithWindowNibName:@"PlainWindowController"]; 
__weak PlainWindowController *weakWindowController = strongWindowController; 

[strongWindowController showWindow:nil]; 

strongWindowController = nil; 
STAssertNil(weakWindowController, @"The window controller should have been deleted, wasn't"); 

在測試中,我寫了這個代碼。

如果我離開了showWindow是零。如果我使用init而不是initWithWindowNibName,則它是零。

有人知道這裏發生了什麼嗎?提前感謝您的任何指導。

回答

2

通常不應懷有的時候,如果他們曾經被傳遞給你不控制其他代碼將被釋放的對象「預期」。

可可可能已經保留,然後自動釋放控制器。可可可能保留正在顯示的任何窗口的窗口控制器。一般來說,當談到Cocoa內存管理時,你應該確保你自己的代碼遵循規則(ARC主要爲你做),你應該假設其他代碼遵循規則,但是你可以'假設其他代碼不會保留超出興趣結束位置的對象。你應該基本上不關心其他代碼在內存管理方面做了什麼。

如果您真的想知道發生了什麼,請在分配工具下運行您的應用程序,並在您希望解除分配的位置後探究對象的保留/釋放/自動釋放歷史記錄。

+0

感謝您的澄清。事實上,如果我在常規應用程序的某個地方初始化該筆尖而沒有任何強大的參考,它會在某個未知的時間(但很快)發生dealloc。由ARC提供的新控件仍然被幕後的autoreleases玷污,這太糟糕了。 – stevel

3

有沒有保證ARC下方的對象還沒有被添加到自動釋放池,在這種情況下,它不會被釋放,直到當前事件的結束。

在你的情況,我強烈懷疑的地方內initWithWindowNibName:控制器得到保留,並自動釋放。

如果你真的想以確保您的對象被釋放,只要繼承了-dealloc方法和添加的NSLog它或它打破。

+0

謝謝你,你是對的,在initWithWindowNibName的某處必須有一個retain/autorelease。不幸的是,在保留週期的情況下(這是我調查這個問題的最初原因),dealloc當然不會被調用。現在我意識到我不能使用這些簡單的單元測試來測試保留週期,我將使用其他方法... – stevel

0

我在第一次使用ARC時遇到過類似的問題。不幸的是我不記得一年多以前的細節。我最終使用儀器來監測保留值,但最終將其作爲一個循環保留問題進行追蹤,儘管並非沒有失去很多頭髮。

我認爲實際的問題是與我固定@property (unsafe_unretained) id delegate;

+0

委託人確實是導致保留週期的常見場所。另一個任何具有定時器目標的對象的對象(定時器保留目標對象,所以如果你的窗口控制器有一個定時器瞄準自己,保留週期)。每天學習一些新的東西:) – stevel

0

我昨天與ARC基於項目遇到了類似的問題,委託 - 一個NSWindowController子類不會取消分配,也沒有-dealloc火災。我曾與殭屍,分配無濟於事。問題很簡單。有在窗內的子類的控制,並且在控制子類的.h頭文件的屬性被定義爲:

@property id delegate; 

校正它

@property (nonatomic, weak) id delegate; 

固定的問題。