NSWindowController子类不会在ARC中发布

时间:2014-01-31 01:51:32

标签: objective-c macos cocoa automatic-ref-counting nswindowcontroller

我遇到了NSWindowController的奇怪情况。我希望窗口控制器被释放,但它不会。它似乎没有遵循我对ARC行为的期望。

我创建了一个简单的窗口控制器子类PlainWindowController。它的接口和实现是空的:

#import <Cocoa/Cocoa.h>

@interface PlainWindowController : NSWindowController
@end

@implementation PlainWindowController
@end

我用它创建了一个名为PlainWindowController.xib的默认windowController xib,它有一个窗口,其中已经设置了委托和windowController连接。

在测试中,我写了这段代码:

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,则为零。

有谁知道这里发生了什么?提前感谢您的任何指导。

4 个答案:

答案 0 :(得分:3)

无法保证ARC下的对象没有添加到自动释放池中,在这种情况下,它将不会在当前事件结束时释放。

在你的情况下,我强烈怀疑控制器被保留并自动释放的位置initWithWindowNibName:内。

如果你真的想确保你的对象被释放,只需继承-dealloc方法并为其添加一个NSLog或中断它。

答案 1 :(得分:2)

如果对象被解除分配,如果它们被传递给您无法控制的其他代码,通常不应该存在“期望”。

Cocoa可能已经保留,然后自动释放控制器。 Cocoa可能会保留正在显示的任何窗口的窗口控制器。

一般来说,当谈到Cocoa内存管理时,你应该确保你自己的代码遵循规则(ARC主要为你做了),你应该假设其他代码遵循规则,但你不能假设其他代码不会保留超出您的兴趣结束的对象。你基本上不应该关心其他代码在内存管理方面做了什么。

如果你真的想知道发生了什么,请在Allocations工具下运行你的应用程序,并在你预期已经解除分配的点之后探索对象的保留/释放/自动释放历史记录。

答案 2 :(得分:0)

首次使用ARC时,我遇到了类似的问题。遗憾的是,我不记得一年多以前的细节了。我最终使用仪器监测保留值,将其作为循环保留问题进行跟踪,尽管并非没有丢失大量头发。

我认为实际问题在于我使用@property (unsafe_unretained) id delegate;

修复的代理

答案 3 :(得分:0)

我昨天遇到了类似的问题,基于ARC的项目 - NSWindowController子类不会解除分配,-dealloc也不会解雇。我曾与Zombies,Allocations合作无济于事。问题很简单。窗口中有一个子类控件,在该控件子类.h头文件中,属性定义为:

@property id delegate;

将其更正为

@property (nonatomic, weak) id delegate;

解决了这个问题。