2011-06-12 184 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池的情况下看到一个异常,所以我猜测只有一个池可以永远不会被耗尽。