¿Por qué la asignación con una propiedad fuerte funciona, pero no con una propiedad débil?

Tengo una propiedad declarada en mi file .h como

@property (weak, nonatomic) UIPickerView *levelPicker; 

que se sintetiza en mi file de implementación como:

 @synthesize levelPicker = _levelPicker; 

Entonces tengo un bloque de código en el mismo file de implementación que hace lo siguiente:

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

En este caso, self._levelPicker no está configurado en el nuevo UIPickerView. Es decir, la asignación self.levelPicker = blah no funciona.

Sin embargo, si cambio la statement de properties a:

 @property (strong, nonatomic) UIPickerView *levelPicker; 

entonces todo funciona como se espera y _levelPicker se establece en el UIPickerView recién asignado.

¿Puede alguien decirme por qué este es el caso? Pensé que estaba entendiendo cómo funcionan las references, pero creo que aún tengo más por aprender. Leí algunas de las otras publicaciones SO relacionadas, pero aún no está del todo claro para mí.

Como dice @Inazfiger, tus objects necesitan al less una reference fuerte (de retención), de lo contrario no serán retenidos.

En este caso, está asignando la vista del selector a la propiedad inputView un inputView . El campo de text conservará la vista del selector (lo sé porque la propiedad inputView en UITextField se declara con los modificadores "readwrite, retain " ), pero solo una vez que haya realizado la asignación . Entonces, si quieres seguir con una reference débil, necesitas reorganizar ligeramente el código, algo así:

 // 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; 

Bueno, la respuesta corta es que la asignación realmente funciona.

Sin embargo, dado que es una reference débil, no se retiene puesto que no hay (otra) fuerte reference a su selector y se establece automáticamente en cero.

Tiene que haber al less una reference fuerte a cualquier object, de lo contrario no se retiene, lo que en este caso no existe.

Para get más información, consulte " ARC presenta nuevos calificadores de por vida " en "Transición a las notas de la versión de ARC" de Apple.

Ray Wenderlich creó un gran tutorial sobre esto aquí .

El calificador "fuerte" crea una relación de propietario que detiene el desasignado del object, lo que es equivalente a lo que haría en el mundo no ARC anteriormente:

 @property(retain) NSObject *obj; 

Si bien el calificador "débil" no crea la relación del propietario, el object se desasignará como lo haría antes:

 @property(assign) NSObject *obj; 

En su caso, necesita la primera relación porque necesita su variable de instancia (_levelPicker) para aferrarse a la instancia UIPickerView recién creada. La asignación débil que realmente trabajó pero fue desasignada poco después.

    Intereting Posts