2011-06-12 182 views
2

在一個應用程序(OS X 10.6.7)中,我有一個NSWindowController子類,它被初始化爲-[NSWindowController initWithWindow:] -i.e.,我已經在代碼中創建了窗口;我沒有從筆尖加載它。- 當NSWindowController用窗口初始化時 - [NSWindowController窗口]保留窗口?

通常,我參考我的NSWindowController子類中的窗口[self window]。但在這種情況下,我每次發送[self window]時,窗口都會被保留下來,所以我最終泄漏了很多。

這是預期的行爲?目前我已經解決了這個問題,只需將窗口存儲在init方法中的實例變量中,並且絕不發送[self window]

我敢肯定這是不會發生,因爲NSWindowController試圖加載窗口:-loadWindow不保留窗口和-isWindowLoaded回報YES

(gdb) set $window = (id)[self window] 
Current language: auto; currently objective-c 
(gdb) p (int)[$window retainCount] 
$1 = 3 
(gdb) p (BOOL)[self isWindowLoaded] 
$2 = 1 '\001' 
(gdb) call (void)[self loadWindow] 
(gdb) p (int)[$window retainCount] 
$3 = 3 
(gdb) p (int)[[self window] retainCount] 
$4 = 4 
(gdb) p (int)[[self window] retainCount] 
$5 = 5 
+0

可能是'-window'做了類似'return [[_window retain] autorelease]'的事情,並且你的調試會話沒有給出相應的autorelease池被排空的機會。有沒有_actual_泄漏? – 2011-06-12 23:26:25

+0

是的,有一個實際的泄漏。注意上面的「關閉前」;這發生在我試圖關閉窗口時,並且保留計數與'[self window]'調用的數量成正比。我剛剛發現了另一個提到這一點:http://www.cocoabuilder.com/archive/cocoa/219582-nswindowcontroller-retain-counts-chapter-2.html – 2011-06-12 23:27:31

+1

我看到該線程已覆蓋'-retain/- autorelease'模式,並且那個不平衡的autorelease池評論很有趣。除此之外,我沒有想法。 – 2011-06-12 23:35:08

回答

2

-[NSWindowController window]護窗的罰款;這個問題似乎與autorelease池有關。

window = [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 100, 200, 200) 
               styleMask:NSTitledWindowMask 
               backing:NSBackingStoreBuffered 
                defer:NO]; 
NSWindowController *controller = [[NSWindowController alloc] initWithWindow:window]; 
[window setTitle:@"testing"]; 
[window makeKeyAndOrderFront:nil]; 
[window release]; 
NSLog(@"[window retainCount]: %d", [window retainCount]); 
[controller window]; 
[controller window]; 
[controller window]; 
NSLog(@"[window retainCount]: %d", [window retainCount]); 

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
[controller window]; 
[controller window]; 
[controller window]; 
NSLog(@"[window retainCount]: %d", [window retainCount]); 
[pool drain]; 
NSLog(@"[window retainCount]: %d", [window retainCount]); 

輸出是:

2011-06-12 19:26:52.337 window[5517:a0b] [window retainCount]: 1 
2011-06-12 19:26:52.339 window[5517:a0b] [window retainCount]: 4 
2011-06-12 19:26:52.340 window[5517:a0b] [window retainCount]: 7 
2011-06-12 19:26:52.340 window[5517:a0b] [window retainCount]: 4 

的問題是,我忘了在碳事件處理程序(InstallApplicationEventHandler)做可可的東西時,創建池。這與我鏈接的線索的上下文匹配。

通常我會在沒有autorelease池的情況下看到一個異常,所以我猜測只有一個池可以永遠不會被耗盡。