Objective-C属性Getter / Setter崩溃EXC_BAD_ACCESS

时间:2015-02-20 20:42:11

标签: objective-c cocoa properties crash null

我想知道为什么为另一个类中的属性赋值会导致EXC_BAD_ACCESS。我似乎无法弄明白为什么。

1。)发送到setter的值是非零的; 2.)当尝试分配值时,EXC_BAD_ACCESS发生,变量为nil;

在Cocoa和Cocoa Touch应用程序中使用此模式都会导致EXC_BAD_ACCESS,所以我不认为它是平台,但我相信它是我使用的模式。

我的问题是,是在分配变量时,还是我创建属性的方式?

我创建了一个虚拟项目,如下图所示。

感谢任何帮助。

enter image description here

enter image description here

编辑:做一些挖掘,我将setter变量(不是属性名称)的名称更改为firstName__。基本上,setFirstName的setter中的代码:

- (void)setFirstName:(NSString *)firstName__
{
    self.firstName = firstName__;
}

通过说firstName__(而不是self.firstName)等于nil,这样做有点混乱,即使在AppDelegate中,该值也是非零的。

1 个答案:

答案 0 :(得分:13)

你的问题是递归。在setter中,您再次调用setter方法,并且一次又一次。 当你宣布

self.firstName = first name__;

基本上相当于

[self setFirstName:first name__];

因此,该方法称自己没有多大意义。

首先需要围绕属性和实例变量。

Objective C类实例通常包含保存值的实例变量。 尽管可以通过@public限定符将这些变量暴露给外部世界,但这不是既定惯例。 惯例是拥有属性,在幕后是一个"包装"围绕私有实例变量。 因为在Objective C中你只能通过消息与其他对象通信,以便能够访问你有setter的实例变量的值和在向对象发送适当的消息时调用的getter方法。

现代目标C 在声明属性时隐式创建实例变量。通常说这些属性由实例变量支持。

通常没有理由显式实现setter和getter,因为编译器会在幕后为您执行此操作。 (以同样的方式,它也为你创建那些实例变量)

但是如果你想明确地实现setter,你需要在setter中设置实例变量,而不是再次调用setter本身(通过点符号约定),如上所述。

隐式创建的实例变量具有以下划线作为前缀的命名约定。在你的情况下它是

_firstName

当您声明名为firstName的属性时,您还会获得一个实例变量
    _FirstName

你的setter应该是这样的

-(void)setFirstName:(NSString *)firstName 
{ 
    _firstName = firstName;
} 

和getter

-(NSstring *)getFirstName
{
    return _firstName;
}