在下面的代码中:
- (void)viewDidLoad {
NSArray *array = [[NSArray alloc] initWithObjects: @"Browny", @"Andy", @"Chiki", @"Gillu",
@"SnowLeopard", @"Lion", @"Tiger", @"SiberianTiger", nil ];
self.pickerData = array;
[array release];
}
如果我在self.pickerData
上方更改为pickerData
,程序将与EXC_BAD_ACCESS signal received
崩溃。
我认为使用关键字self
的对象的成员变量/属性是可选的吗?
任何提示,为什么我在这里需要self
,即使pickerData
是该类的成员变量?
答案 0 :(得分:5)
将其包装在一个答案中,而不是点缀其他答案。
致电时
self.pickerData = array;
这是编译为
[self setPickerData:array];
如果您@sythesize
pickerData
,实施将采取类似的措施:
- (void)setPickerData:(NSArray *)_pickerData;
{
if (pickerData != _pickerData) {
[pickerData release];
pickerData = [_pickerData retain];
}
}
不同之处在于self.pickerData = array
将通过将执行正确内存管理的setter,而pickerData = array
将直接分配值。
答案 1 :(得分:1)
这是因为当您执行self.something = value
时,会为值调用retain
。当您删除 self 时,它将不会保留,并且当您在方法返回之前释放变量 array 时,“pickerData”将指向无效的内存位置。
因此,您必须保留 self ,或手动保留它,例如pickerData = [array retain];
答案 2 :(得分:0)
self.pickerData = array;
与[self setPickerData:array]
相同,如果使用retain声明属性,则为:{/ p>
-(void)setPickerData:(NSArray *)_pickerData
{
id t = pickerData;
pickerData = [_pickerData retain];
[t release];
}
在没有属性的示例中,您最终会立即释放数组,但iVar pickerData仍指向它,下次您尝试使用它时很可能会崩溃。
答案 3 :(得分:0)
正如其他答案所示,self.property
构造不仅仅是简单的语法(它调用了setter和getter方法)。
然而,合成的吸气剂只返回底层的ivar,所以在右手边的表达式中,你可以在实践中交替使用合成的吸气剂或ivars。
就个人而言,我更喜欢使用左手侧和右手侧表达式的相同风格,所以一旦我使用了setter,我也会尝试使用getter。但说实话,这是风格和个人品味的问题。
答案 4 :(得分:0)
执行以下代码时:
NSArray *array = [[NSArray alloc] initWithObjects: @"Browny", @"Andy", @"Chiki", @"Gillu",
@"SnowLeopard", @"Lion", @"Tiger", @"SiberianTiger", nil ];
array
的保留计数为1。
如果由于setter方法选择使用self.pickerData = array;
,则数组的保留计数将为2.然后,在执行[array release];
后,数组的保留计数将再次为1,它将保留是pickerData。
但是,如果使用pickerData = array
,则数组的保留计数仍为1,因为没有执行retain
。因此,在[array release];
之后,pickerData的保留计数将变为0,而pickerData仍在使用。因此崩溃。
我认为@ Paul.s已经解决了一个相当不错的答案,关键是当使用关键字self
时,setter方法是不同的。我在另一个角度回答它,希望它可以有用而且更简单。