Objective-C 属性 Getter/Setter 崩溃 EXC_BAD_ACCESS
Objective-C Property Getter/Setter crash EXC_BAD_ACCESS
我想知道为什么给另一个 class 中的属性赋值会导致 EXC_BAD_ACCESS。我似乎无法弄清楚为什么。
1.) 发送到 setter 的值不是零;
2.) 尝试赋值时,EXC_BAD_ACCESS 发生,变量为 nil;
在 Cocoa 和 Cocoa Touch 应用程序中使用此模式都会导致 EXC_BAD_ACCESS,所以我不认为这是平台问题,但我相信这是我的模式使用。
我的问题是,是在分配变量时,还是我创建属性的方式?
我创建了一个虚拟项目,如下图所示。
感谢任何帮助。
编辑:进行一些挖掘,我将 setter 的变量名称(不是 属性 名称)更改为 firstName__。基本上,setter 中的代码用于 setFirstName:
- (void)setFirstName:(NSString *)firstName__
{
self.firstName = firstName__;
}
通过说 firstName__(而不是 self.firstName)等于 nil,即使在 AppDelegate 中,该值不为 nil,这样做也消除了一些混乱。
你的问题是递归。在 setter 中,您一次又一次地调用 setter 方法。
当你声明
self.firstName = first name__;
基本上等同于
[self setFirstName:first name__];
所以该方法正在调用自身,这没有多大意义。
您首先需要了解属性和实例变量。
Objective C class 实例通常包含保存值的实例变量。
尽管可以通过 @public 限定符将这些变量暴露给外界,但这不是既定的约定。
约定是要有属性,在幕后是 "wrapper" 围绕 私有实例变量 。
由于在 Objective C 中您只能通过消息与其他对象通信,因此为了能够访问实例变量的值,您可以在发送适当的消息时调用 setter 和 getter 方法到对象。
现代 objective C 在您声明属性时隐式地为您创建实例变量。人们常说这些属性由实例变量支持。
通常没有理由显式实现 setters 和 getters,因为编译器会在幕后为您完成。 (以同样的方式,它也为你创建了那些实例变量)
但是如果要显式实现setters,需要在setter中设置实例变量,而不是调用[=54] =] 本身(通过点符号约定),正如我上面解释的那样。
隐式创建的实例变量具有以下划线作为前缀的命名约定。在你的情况下是
_firstName
当你声明一个名为 firstName 的 属性 时,你也会得到一个实例变量
_名字
你setter应该是这样的
-(void)setFirstName:(NSString *)firstName
{
_firstName = firstName;
}
和getter
-(NSstring *)getFirstName
{
return _firstName;
}
我想知道为什么给另一个 class 中的属性赋值会导致 EXC_BAD_ACCESS。我似乎无法弄清楚为什么。
1.) 发送到 setter 的值不是零; 2.) 尝试赋值时,EXC_BAD_ACCESS 发生,变量为 nil;
在 Cocoa 和 Cocoa Touch 应用程序中使用此模式都会导致 EXC_BAD_ACCESS,所以我不认为这是平台问题,但我相信这是我的模式使用。
我的问题是,是在分配变量时,还是我创建属性的方式?
我创建了一个虚拟项目,如下图所示。
感谢任何帮助。
编辑:进行一些挖掘,我将 setter 的变量名称(不是 属性 名称)更改为 firstName__。基本上,setter 中的代码用于 setFirstName:
- (void)setFirstName:(NSString *)firstName__
{
self.firstName = firstName__;
}
通过说 firstName__(而不是 self.firstName)等于 nil,即使在 AppDelegate 中,该值不为 nil,这样做也消除了一些混乱。
你的问题是递归。在 setter 中,您一次又一次地调用 setter 方法。 当你声明
self.firstName = first name__;
基本上等同于
[self setFirstName:first name__];
所以该方法正在调用自身,这没有多大意义。
您首先需要了解属性和实例变量。
Objective C class 实例通常包含保存值的实例变量。 尽管可以通过 @public 限定符将这些变量暴露给外界,但这不是既定的约定。 约定是要有属性,在幕后是 "wrapper" 围绕 私有实例变量 。 由于在 Objective C 中您只能通过消息与其他对象通信,因此为了能够访问实例变量的值,您可以在发送适当的消息时调用 setter 和 getter 方法到对象。
现代 objective C 在您声明属性时隐式地为您创建实例变量。人们常说这些属性由实例变量支持。
通常没有理由显式实现 setters 和 getters,因为编译器会在幕后为您完成。 (以同样的方式,它也为你创建了那些实例变量)
但是如果要显式实现setters,需要在setter中设置实例变量,而不是调用[=54] =] 本身(通过点符号约定),正如我上面解释的那样。
隐式创建的实例变量具有以下划线作为前缀的命名约定。在你的情况下是
_firstName
当你声明一个名为 firstName 的 属性 时,你也会得到一个实例变量
_名字
你setter应该是这样的
-(void)setFirstName:(NSString *)firstName
{
_firstName = firstName;
}
和getter
-(NSstring *)getFirstName
{
return _firstName;
}