跳过成员变量的“self”关键字会导致程序崩溃

时间:2011-12-03 21:10:13

标签: iphone objective-c ios cocoa-touch

在下面的代码中:

- (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是该类的成员变量?

5 个答案:

答案 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方法是不同的。我在另一个角度回答它,希望它可以有用而且更简单。