Почему назначение с сильным свойством работает, а не со слабым? - PullRequest
3 голосов
/ 10 марта 2012

У меня есть свойство, объявленное в моем файле .h как

@property (weak, nonatomic) UIPickerView *levelPicker;

, которое синтезировано в моем файле реализации как:

@synthesize levelPicker = _levelPicker;

У меня есть блок кода в том жефайл реализации, который выполняет следующее:

if (self.levelPicker == nil) {
    self.levelPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
    self.levelPicker.delegate = self;
    self.levelPicker.dataSource = self;
}
textField.inputView = self.levelPicker;

В этом случае self._levelPicker не установлен в новый UIPickerView.Т.е. назначение self.levelPicker = blah не работает.

Однако, если я изменяю объявление свойства на:

@property (strong, nonatomic) UIPickerView *levelPicker;

, тогда все работает, как ожидается, и _levelPicker устанавливается на вновьвыделенный UIPickerView.

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

Ответы [ 3 ]

7 голосов
/ 10 марта 2012

Как говорит @Inazfiger, ваши объекты должны иметь хотя бы одну сильную (сохраняющую) ссылку, иначе они не будут сохранены.

В этом случае вы назначаете представление выбора свойству UITextField inputView. Текстовое поле сохранит представление выбора (я знаю это, потому что свойство inputView в UITextField объявлено с модификаторами readwrite, retain"), но только после того, как вы сделали назначение . Поэтому, если вы хотите придерживаться слабой ссылки, вам нужно немного изменить код - примерно так:

// Declare a temporary UIPickerView reference. By default, this is
// a strong reference - so tempPicker will be retained until this
// variable goes out of scope.
UIPickerView *tempPicker = [[UIPickerView alloc] initWithFrame:frame];

// Configure the picker
tempPicker.delegate = self;
tempPicker.dataSource = self;

// Assign the picker view to the text field's inputView property. This
// will increase the picker's retain count. Now it'll no longer be
// released when tempPicker goes out of scope.
textField.inputView = tempPicker;

// Finally, assign the same object to self.levelPicker - it won't
// go out of scope as long as it remains assigned to textField's
// inputView property, and textField itself remains retained.
self.levelPicker = tempPicker;
4 голосов
/ 10 марта 2012

Ну, краткий ответ: назначение действительно работает.

Однако, поскольку это слабая ссылка, она не сохраняется, поскольку нет (другой) сильной ссылки на ваш сборщик и егоавтоматически устанавливается на ноль.

Должна быть хотя бы одна сильная ссылка на любой объект, в противном случае он не сохраняется, чего в данном случае нет.

Для получения дополнительной информации,см. « ARC представляет новые Lifetime Qualifiers » в «Переходе к заметкам о выпуске ARC» от ​​Apple.

Рэй Вендерлих (Ray Wenderlich) создал большое руководство по этому здесь .

1 голос
/ 10 марта 2012

Спецификатор "strong" создает отношение владельца, которое останавливает освобождение объекта, что эквивалентно тому, что вы делали ранее в мире без ARC:

@property(retain) NSObject *obj;

Хотя «слабый» квалификатор не создает отношения владельца, поэтому объект будет освобожден, как вы делали это раньше:

@property(assign) NSObject *obj;

В вашем случае вам нужны первые отношения, потому что вам нужна переменная экземпляра (_levelPicker), чтобы удерживать только что созданный экземпляр UIPickerView. Слабое задание, которое вы действительно выполняли, но вскоре после этого было отменено.

...