пропуск слова «self» для переменной-члена приводит к сбою программы - PullRequest
1 голос
/ 04 декабря 2011

В приведенном ниже коде:

- (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 ]

5 голосов
/ 04 декабря 2011

Чтобы заключить его в один ответ, а не разбивать на другие ответы.

Когда вы звоните

self.pickerData = array; 

это скомпилировано в

[self setPickerData:array];

Если вы @sythesize pickerData, реализация сделает что-то похожее на:

- (void)setPickerData:(NSArray *)_pickerData;
{
    if (pickerData != _pickerData) {
        [pickerData release];
        pickerData = [_pickerData retain];
    }
}

Таким образом, разница в том, что self.pickerData = array будет проходить через установщик, который будет выполнять правильное управление памятью, тогда как pickerData = array присваивает значение напрямую.

1 голос
/ 04 декабря 2011

Это происходит потому, что когда вы делаете self.something = value, retain вызывается для значения .Когда вы удаляете self , он не будет сохраняться, и когда вы освобождаете переменную array непосредственно перед возвратом метода, «pickerData» будет указывать на недопустимое расположение в памяти.

Итак, вы должны оставить себя или сохранить его вручную, как pickerData = [array retain];

0 голосов
/ 02 июля 2012

Когда были выполнены следующие коды:

NSArray *array = [[NSArray alloc] initWithObjects: @"Browny", @"Andy", @"Chiki", @"Gillu",
                      @"SnowLeopard", @"Lion", @"Tiger", @"SiberianTiger", nil ];

счет сохранения array будет равен 1.

Если вы решите использовать self.pickerData = array; из-за метода установки,счетчик сохранения массива будет равен 2. Затем, после выполнения [array release]; счетчик сохранения массива снова будет равен 1, он будет сохранен как pickerData.

Однако, если используется pickerData = array, счетчик сохранения массивабудет по-прежнему 1, так как retain не было выполнено.Следовательно, после [array release]; счетчик сохранения pickerData станет 0, тогда как pickerData все еще используется.Поэтому сбой.

Я думаю, что @ Paul.s дал достаточно хороший ответ, ключевой момент в том, что метод установки отличается, когда используется ключевое слово self.Настоящим я отвечаю на это в другой перспективе, надеясь, что это может быть полезным и более простым.

0 голосов
/ 06 декабря 2011

Как показывают другие ответы, конструкция self.property - это гораздо больше, чем простой синтаксис (она вызывает методы setter и getter).

Однако, синтезированные геттеры просто возвращают базовый ивар, поэтому в выражениях с правой стороны вы можете на практике использовать синтезированные геттеры или ивары взаимозаменяемо.

Лично я предпочитаю использовать один и тот же стиль доступа для выражений как левой, так и правой стороны, поэтому, когда я использую сеттеры, я также стараюсь использовать геттеры повсюду. Но это, честно говоря, вопрос стиля и личного вкуса.

0 голосов
/ 04 декабря 2011

self.pickerData = array; это то же самое, что и [self setPickerData:array], который, если ваша собственность объявлена ​​с помощью retain, выглядит примерно так:

-(void)setPickerData:(NSArray *)_pickerData
{
    id t = pickerData;
    pickerData = [_pickerData retain];
    [t release];
}

в вашем примере без свойства вы в конечном итоге освобождаете массив сразу после этого, но iVar pickerData по-прежнему указывает на него, и в следующий раз, когда вы попытаетесь использовать его, вы, скорее всего, вылетите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...