【问题标题】:NSWindowController subclass will not release in ARCNSWindowController 子类不会在 ARC 中发布
【发布时间】:2014-01-31 01:51:32
【问题描述】:

我在使用 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,则为nil。

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

【问题讨论】:

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


    【解决方案1】:

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

    在您的情况下,我强烈怀疑在 initWithWindowNibName: 内的某个地方,控制器会被保留并自动释放。

    如果你真的想确保你的对象被释放,只需子类化 -dealloc 方法并向其添加 NSLog 或中断它。

    【讨论】:

    • 谢谢你,你是对的,在 initWithWindowNibName 的某个地方一定有一个保留/自动释放。不幸的是,在保留周期的情况下(这是我调查这个问题的最初原因),当然不会调用 dealloc。现在我意识到我不能使用这些简单的单元测试来测试保留周期,我将使用其他方法......
    【解决方案2】:

    如果对象曾经被传递给您无法控制的其他代码,您通常不应该对何时释放对象抱有“期望”。

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

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

    如果您真的想知道发生了什么,请在 Allocations 工具下运行您的应用,并在您预期对象被释放后探索对象的保留/释放/自动释放历史记录。

    【讨论】:

    • 感谢您的澄清。事实上,如果我在没有任何强引用的情况下在常规应用程序中的某个地方初始化 nib,它会解除分配(在某个未知时间,但很快)。 ARC 提供的新控制仍然被幕后的自动发布所玷污,这太糟糕了。
    【解决方案3】:

    我在第一次使用 ARC 时遇到了类似的问题。不幸的是,我不记得细节了,因为这是一年多前的事了。我最终将其作为循环保留问题进行了追踪,使用 Instruments 来监控保留值,尽管并非没有损失很多头发。

    我认为实际问题出在我用@property (unsafe_unretained) id delegate; 修复的委托

    【讨论】:

    • 委托确实是导致保留周期的常见地方。另一种是任何带有定时器的对象(定时器会保留目标对象,因此如果您的窗口控制器有一个定时器以自身为目标,则保留周期)。每天学习新东西:)
    【解决方案4】:

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

    @property id delegate;
    

    改正

    @property (nonatomic, weak) id delegate;
    

    修复了问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      相关资源
      最近更新 更多