【问题标题】:Obj-C memory management for an NSView * instance variableNSView * 实例变量的 Obj-C 内存管理
【发布时间】:2011-01-08 21:58:31
【问题描述】:

我的自定义视图有一个子视图作为实例变量。 这是一个示例界面:

@interface MyCustomView : NSView {
    NSView *aSubview;
}

@end

然后,在 .m 文件中,我初始化 aSubView 并将其添加到自定义视图中。

- (id)init
{
    self = [super initWithFrame:CGRectMakeFrame(0.0, 0.0, 320.0, 480.0);
    if (self) {
        aSubview = [[NSView alloc] initWithFrame(0.0, 0.0, 100.0, 100.0);

        [self addSubview:aSubview];
    }
    return self;
}

我应该在哪里释放aSubView

-dealloc 方法中?

- (void)dealloc
{
    [aSubView release];
    [super dealloc];
}

或者直接在-init方法中添加到自定义视图之后?

- (id)init
{
    [...]
    [self addSubview:aSubview];
    [aSubview release];
    [...]
}

哪一个是最好的实现?

【问题讨论】:

  • 您创建它并将其添加为子视图,这意味着您拥有它两次。您的选择是立即释放创建所有权并在视图的剩余生命周期中仅拥有一次,或者在整个时间中保留实例变量中的子视图并在其末尾将其释放到dealloc。只要两种所有权都通过发布来平衡,两种方式都同样有效。
  • 不完全;如果你有一个实例变量作为参考,你应该保留一个直到 dealloc (如果那是你的预期寿命)。最不脆弱的方法是在任何给定的保留引用的生命周期内始终保留保留。当然,面对保留周期(有时这是魔鬼的工作),这会崩溃。所以...我建议在dealloc 中释放以平衡初始化方法中隐含的retain
  • 哦,aSubview 是一个非典型的 ivar 名称。 subviewcontainedView 会更有意义。 aSubview 作为方法的参数会更典型。
  • @bbum 不注意变量名,只是我放在那里为问题编写一些示例代码的占位符。显然,我实际处理的代码比这更复杂,并且对变量使用更合理的名称。

标签: objective-c cocoa memory-management


【解决方案1】:

您的代码中有两个保留,用于不同的目的。最好将它们分开。

保留 #1

aSubview = [[NSView alloc] initWithFrame(0.0, 0.0, 100.0, 100.0); 暗示了第一个保留。由于aSubview 是一个实例变量,并且您似乎希望在初始化程序运行后保留aSubview 作为对视图的有效引用,因此隐含的保留将由release 中的dealloc 平衡是有道理的.

保留 #2

当添加到视图层次结构中时,您的视图实例将被它作为子视图的任何视图保留。在这种情况下它是self 是无关紧要的。只要视图是视图层次结构的一部分,保留就会生效。当它被删除时,它将被释放。


两者是对象寿命的正交实现。将它们分开可以让您的代码不那么脆弱。

例如,如果在将来的某个版本中,您偶尔会从视图层次结构中删除视图,并希望稍后将其保留——最终的显示/隐藏,如果你愿意的话——那么 保留 #1 上面将保留它。

同样,如果您有一天想忘记当前视图,而是将其替换为不同的视图,您可以这样做:

[aSubview release];
aSubview = [[.... alloc] ... init ... ];

而且,在这种情况下,上面的 retain #2 将使旧视图在视图层次结构中保持活动状态。

【讨论】:

    【解决方案2】:

    我会说您应该在将“aSubview”添加到视图后直接释放它。 (即:一旦它被保留在其他地方。)

    但是,我还要说,将“aSubview”作为实例变量没有任何价值 - 它应该只是 init 方法中的局部变量。

    【讨论】:

    • “价值”是我可以在我的自定义视图的其他方法中直接访问实例变量,而不是处理子视图数组。如果我错了,请纠正我。
    • @massimoperi 如果是这样,那么我很想在 dealloc 中释放它,因为这对于实例变量来说感觉更自然。
    • 我同意它感觉更自然和传统。另一方面,我将有一个保留计数为 2 的实例变量,而第一个解决方案的保留计数仅为 1。但也许保留计数并不那么重要。
    • @massimoperi 只要你在你的 dealloc 中释放它,它最终的保留计数就会为零,这才是真正重要的,除非你当然打算摆脱子视图并保留你的类,在这种情况下,我会放弃实例变量(必要时通过子视图数组访问)并在将其添加到视图后释放它。
    【解决方案3】:

    我更喜欢dealloc,因为当你的对象包含其他对象时,你必须在你自己dealloc时释放它们。

    【讨论】:

      猜你喜欢
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 2010-09-27
      • 2012-01-24
      相关资源
      最近更新 更多