我不知道为什么我得到EXC_BAD_ACCESS(使用@property保留)

时间:2011-04-05 20:37:55

标签: iphone properties release

.h

@ interface MyClass : NSObject {
   UILabel *mTextLabel;
}

@property (nonatomic, retain) UILabel *mTextLabel;

并在MyClass.m中声明 @synthesize mTextLabel ;

并像这样释放对象。

[self setMTextLabel:nil];
[mTextLabel release];
NSLog (@"%d",[mTextLabel retainCount]);

此结果为0.我没有发现任何错误或中断。

但是。当我像这样发布mTextLabel时。我刚刚获得了EXC_BAD_ACCESS

[mTextLabel release];
[self setMTextLabel:nil];

我不明白为什么会这样。 Plz帮助我。

3 个答案:

答案 0 :(得分:6)

当你有一个带有retain属性的合成属性时,合成的setter会在设置新值之前调用旧ivar上的release。

以下是第一个示例中发生的事情的扩展视图:

[mTextLabel release];
mTextLabel = nil;
[mTextLabel release];

由于在nil指针上调用方法什么都不做,所以没有问题。

在第二个例子中,这是正在发生的事情:

[mTextLabel release];
[mTextLabel release];
mTextLabel =  nil;

看到问题?

编辑:值得注意的是,检查对象的保留计数很少有用,因为任何数量的Cocoa类都可以为自己的目的保留它。您只需要确保每次在对象上调用retainalloccopynew时,都会匹配release或{{ 1}}代码中的某个地方。

答案 1 :(得分:1)

问题是你正在调用release然后你将属性设置为nil,在将它设置为nil之前也会向mTextLabel发送一个版本。这是将属性定义为复制或保留时发生的情况。您只需要以下代码。

[mTextLabel release];
mTextLabel = nil;

修改

我想在init和dealloc之外的代码中添加它,如果必要的话,调用self.mTextLabel = nil正确释放并且属性的值为n是完全正确的。但建议NOT use the property in the init/dealloc calls。在这些情况下,您需要直接创建/释放对象以避免访问者的副作用。

答案 2 :(得分:0)

执行[self setMTextLabel:nil]时,该值已经释放。您不需要显式释放值(除非您使用initcopy方法创建了值,在这种情况下,您应该在分配到{{1}后立即释放它})。

请注意retainCount has a return type of NSUInteger,因此永远不会消极。因此,检查以确保保留计数为零而不是-1不起作用。