我需要在dealloc中释放吗?

时间:2010-03-01 17:01:44

标签: objective-c iphone

在我正在为iPhone开发人员学习的书中,他们使用Interface Builder来使用IBOutlet个实例。一个例子是UIButton。所以他们在结构中添加了这样的东西:

 IBOutlet UIButton *whateverButton;

然后他们为.h中的每一个添加@property,在.m中添加@synthesize

然后他们在.m的release中包含dealloc。两个问题:

  1. 是否需要发布?是不是已经自动处理了所有属性?
  2. 我如何查看引用计数以查看发生了什么,以便进行调试......?

3 个答案:

答案 0 :(得分:5)

属性不是“自动处理”。最接近的是合成访问器正确处理其内存管理职责。但那只是那些访问者。属性只是在课堂上声明可访问的“事物”的一种方式。除此之外,他们没有得到太多特殊待遇。它没有打开某种垃圾收集。所以是的,发布是必要的。

如果要检查正在运行的应用程序是否存在泄漏或未释放的内存,则应使用像Instruments这样的调试工具。我不会直接查看引用计数,因为它几乎是危险无用的 - 无法保证引用计数将是您在任何时候所期望的,并且这并不一定表示存在问题。

你应该阅读Apple的memory management rules for Cocoa。一旦你吸收了它,这很简单。我不一定会建议首先阅读其他指南,因为细微的错误陈述会导致你走错路(例如,为你释放属性的想法可能来自于听到有人错误地说明它们是如何工作的。)

答案 1 :(得分:5)

  

是否需要发布?不是全部   已处理的属性   自动?

如果保留该属性,则必须发布该版本。当您声明@property@synthesize时,您获得的只是访问者,dealloc中没有特殊的自动行为。

此外,IBOutlet没有任何神奇之处 - 它只是Interface Builder的标记,可以查看您希望在IB中显示哪些属性。它只是一个空的宏,Cmd-单击IBOutlet关键字以查看其定义:

#ifndef IBOutlet
#define IBOutlet
#endif

同样适用于扩展到void的IBAction。

  

如何检查参考计数以查看   发生了什么,调试   目的...?

当我需要调试内存管理时,我通常只是在dealloc方法中设置一个断点或在那里记录一个字符串。将对象的retainCount记录在可能与之相关的调用周围也很有帮助。


查看@synthesize指令如何创建访问器也可能有所帮助。当你声明一个保留的@property并要求编译器@synthesize时,你会得到这样的结果:

@property(retain) NSString *foo;
@synthesize foo;

- (void) foo {
    return foo;
}

- (void) setFoo: (NSString*) newFoo {
    // Try to think what would happen if this condition wasn’t
    // here and somebody called [anObject setFoo:anObject.foo].
    if (newFoo == foo)
        return;
    [foo release];
    foo = [newFoo retain];
}

这不完全是事情,但它足够接近。现在应该更清楚为什么你应该在dealloc中发布。

答案 2 :(得分:3)

  

是否需要发布?不是全部   已处理的属性   自动?

这取决于财产的实施方式。如果它是自动实现的(@synthesize'd),则属性将在setter中保留其值,并在设置为其他值时释放它。如果您刚进入Obj-C和Cocoa,您应该阅读有关内存管理的约定。我在我的博客上提到了post,其他地方也有很多资源。

  

如何检查参考计数以查看   发生了什么,调试   目的...?

您可以检查NSObject的retainCount属性。有关的信息是here。出于高级调试目的,存在NSZombieEnabled环境标志,该标志将导致所有释放消息不递减引用计数,但在访问通常已释放的对象时记录错误。