ios - Objective-C ARC: fuerte vs retener y débil vs asignar
ios5 properties (8)
Fuerte:
- La propiedad no se destruirá, pero solo una vez que establezca la propiedad en nulo se destruirá el objeto
- Por defecto, todas las variables de instancia y las variables locales son punteros fuertes.
- Usas fuerte solo si necesitas retener el objeto.
- Por lo general, usamos fuerte para UIViewControllers (los padres de los elementos de UI)
- IOS 4 (no ARC) Podemos usar la clave de retención
- IOS 5 (ARC) Podemos usar palabras clave fuertes
Ejemplo: @property (fuerte, no atómico) ViewController * viewController;
@synthesize viewController;
Débiles
De forma predeterminada, se obtiene automáticamente y se establece en nulo
- Generalmente usamos débil para IBOutlets (UIViewController''s Childs) y delegado
- Lo mismo que asignar, no retener o liberar.
Ejemplo: @ propiedad (débil, no atómica) IBOutlet UIButton * myButton;
@synthesize myButton;
Hay dos nuevos atributos de administración de memoria para las propiedades introducidas por ARC, strong
y weak
.
Aparte de la copy
, que obviamente es algo completamente diferente, ¿hay alguna diferencia entre strong
vs retain
y weak
vs assign
?
A mi entender, la única diferencia aquí es que weak
asignará nil
al puntero, mientras que assign
no, lo que significa que el programa se bloqueará cuando le envíe un mensaje al puntero una vez que se haya soltado. Pero si uso weak
, esto nunca sucederá, porque el envío de mensajes a nil
no hará nada.
No sé de ninguna diferencia entre strong
y retain
.
¿Hay alguna razón por la que debo usar assign
y retain
en nuevos proyectos, o son el tipo de desaprobación?
no atómico / atómico
- no atómico es mucho más rápido que atómico
- siempre use no atómico a menos que tenga un requisito muy específico para atómico, lo que debería ser raro (atómico no garantiza la seguridad de los subprocesos; solo se detiene el acceso a la propiedad cuando otro subproceso lo establece simultáneamente)
fuerte / débil / asignar
- use strong para retener objetos, aunque la palabra clave retener es sinónimo, es mejor usar strong en lugar de
- use débil si solo quiere un puntero al objeto sin retenerlo - útil para evitar ciclos de retención (es decir, delegados) - automáticamente eliminará el puntero cuando se libere el objeto
- usar asignar para primativos: exactamente igual que débil, excepto que no elimina el objeto cuando se libera (establecido de forma predeterminada)
(Opcional)
dupdo
- Úsalo para crear una copia superficial del objeto.
- es una buena práctica establecer siempre las propiedades inmutables para copiar, ya que las versiones mutables se pueden pasar a propiedades inmutables, la copia garantizará que siempre se tratará con un objeto inmutable
- si se pasa un objeto inmutable, lo retendrá - si se pasa un objeto mutable, lo copiará
solo lectura
- Úselo para deshabilitar la configuración de la propiedad (evita que el código se compile si hay una infracción)
- puede cambiar lo que entrega el captador ya sea cambiando la variable directamente a través de su variable de instancia, o dentro del propio método getter
De las Notas de la versión de Transición a ARC (el ejemplo en la sección sobre atributos de propiedad).
// The following declaration is a synonym for: @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;
Tan strong
es lo mismo que retain
en una declaración de propiedad.
Para los proyectos ARC usaría strong
lugar de retain
, usaría assign
para propiedades primitivas C y weak
para referencias débiles a objetos Objective-C.
Después de leer tantos artículos de publicaciones de y aplicaciones de demostración para comprobar los atributos de propiedades variables, decidí reunir toda la información de los atributos:
- atómico // predeterminado
- no atómico
- fuerte = retener // por defecto
- débiles
- conservar
- asignar // predeterminado
- unsafe_unretained
- dupdo
- solo lectura
- readwrite // predeterminado
A continuación se encuentra el enlace detallado del artículo donde puede encontrar todos los atributos mencionados anteriormente, que definitivamente lo ayudarán. Muchas gracias a todas las personas que dan las mejores respuestas aquí !!
1.strong (iOS4 = retener)
- dice "mantén esto en el montón hasta que no lo señale más"
- en otras palabras, "Soy el propietario, no puede desasignar esto antes de apuntar bien con eso mismo como retener"
- Usas fuerte solo si necesitas retener el objeto.
- Por defecto, todas las variables de instancia y las variables locales son punteros fuertes.
- Por lo general, usamos fuerte para UIViewControllers (los padres de los elementos de UI)
- strong se usa con ARC y, básicamente, le ayuda a usted, al no tener que preocuparse por el recuento de un objeto. ARC lo libera automáticamente para usted cuando haya terminado con él. El uso de la palabra clave fuerte significa que usted posee el objeto.
Ejemplo:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2. débil
- dice "mantén esto mientras alguien más lo apunte fuertemente"
- Lo mismo que asignar, no retener o liberar.
- Una referencia "débil" es una referencia que no conserva.
- Por lo general, usamos débil para IBOutlets (UIViewController''s Childs). Esto funciona porque el objeto secundario solo necesita existir mientras lo haga el objeto principal.
- una referencia débil es una referencia que no protege el objeto al que se hace referencia de la recolección por parte de un recolector de basura.
- Débil es esencialmente asignar, una propiedad no retenida. Excepto cuando el objeto se desasigna, el puntero débil se establece automáticamente en nulo
Ejemplo:
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
Explicación fuerte y débil, gracias a BJ Homer :
Imagina que nuestro objeto es un perro y que el perro quiere huir (ser desasignado).
Punteros fuertes son como una correa en el perro. Mientras tengas la correa atada al perro, el perro no huirá. Si cinco personas atan su correa a un perro, (cinco punteros a un objeto), entonces el perro no huirá hasta que las cinco correas estén sueltas.
Los punteros débiles, por otro lado, son como niños pequeños que señalan al perro y dicen "¡Mira! ¡Un perro!" Mientras el perro todavía esté en la correa, los niños pequeños todavía pueden ver al perro, y todavía lo señalarán. Sin embargo, tan pronto como se sueltan todas las correas, el perro huye, sin importar cuántos niños pequeños lo señalen.
Tan pronto como el último puntero fuerte (correa) ya no apunte a un objeto, el objeto se desasignará y todos los punteros débiles se pondrán a cero.
Cuando usamos débil?
La única vez que querría usar debilidad es si quisiera evitar los ciclos de retención (por ejemplo, el padre retiene al niño y el niño retiene al padre para que ninguno sea liberado).
3. Retener = fuerte
- se retiene, se libera el valor antiguo y se asigna retener especifica el nuevo valor que debe enviarse
- retener en la asignación y el valor antiguo enviado - liberación
- Mantener es lo mismo que fuerte.
- Apple dice que si escribes retener, se convertirá automáticamente / solo funcionará como fuerte.
- Los métodos como "alloc" incluyen una "retención" implícita
Ejemplo:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4. asigna
- asignar es el predeterminado y simplemente realiza una asignación de variable
- asignar es un atributo de propiedad que le dice al compilador cómo sintetizar la implementación del establecedor de la propiedad
- Utilizaría asignar para propiedades primitivas C y débil para referencias débiles a objetos Objective-C.
Ejemplo:
@property (nonatomic, assign) NSString *address;
@synthesize address;
El documento de Clang sobre el conteo automático de referencias (ARC) de Objective-C explica claramente los calificadores y modificadores de propiedad:
Hay cuatro calificativos de propiedad:
- __ autoreleasing
- __ fuerte
- __ * unsafe_unretained *
- __ débil
Un tipo no es trivialmente calificado por la propiedad si está calificado con __ autoreleasing , __ fuerte o __ débil .
Luego hay seis modificadores de propiedad para la propiedad declarada:
- asignar implica propiedad __ * unsafe_unretained *.
- copia implica __ propiedad fuerte , así como el comportamiento habitual de la semántica de copia en el configurador.
- retener implica __ fuerte propiedad.
- fuerte implica __ fuerte propiedad.
- * unsafe_unretained * implica __ * unsafe_unretained * propiedad.
- débil implica __ propiedad débil .
Con la excepción de los débiles , estos modificadores están disponibles en modos sin ARC.
En cuanto a la semántica, los calificadores de propiedad tienen un significado diferente en las cinco operaciones administradas : Lectura, Asignación, Inicialización, Destrucción y Mudanza, en las que la mayoría de las veces solo nos preocupamos por la diferencia en la operación de Asignación.
La asignación ocurre cuando se evalúa un operador de asignación. La semántica varía en función de la calificación:
- Para __ objetos fuertes , el nuevo pointee se retiene primero; en segundo lugar, el lvalue se carga con semántica primitiva; tercero, el nuevo pointee se almacena en el lvalor con semántica primitiva; y, finalmente, se libera el antiguo pointee. Esto no se realiza atómicamente; se debe utilizar la sincronización externa para hacer esto seguro frente a las cargas y almacenes concurrentes.
- Para __ objetos débiles , el lvalue se actualiza para apuntar al nuevo pointee, a menos que el nuevo pointee sea un objeto actualmente en proceso de desasignación, en cuyo caso el lvalue se actualiza a un puntero nulo. Esto debe ejecutarse de forma atómica con respecto a otras asignaciones al objeto, a las lecturas del objeto y al lanzamiento final del nuevo pointee.
- Para los objetos __ * unsafe_unretained *, el nuevo pointee se almacena en el valor l utilizando semántica primitiva.
- Para __ objetos de autoreleasing , el nuevo pointee se retiene, se libera automáticamente y se almacena en el lvalue utilizando semántica primitiva.
La otra diferencia en lectura, inicio, destrucción y movimiento, consulte la Sección 4.2 Semántica en el documento .
Las diferencias entre fuerte y retener:
- En iOS4, fuerte es igual a retener
- Significa que eres dueño del objeto y lo mantienes en el montón hasta que no lo apuntes más.
- Si escribes retener funcionará automáticamente igual de fuerte
Las diferencias entre debilidad y asignación:
- Una referencia “débil” es una referencia que no retiene y la mantiene siempre que alguien más la apunte con firmeza.
- Cuando el objeto está "desasignado", el puntero débil se establece automáticamente en nulo
- Un atributo de propiedad "asignar" le dice al compilador cómo sintetizar la implementación del establecedor de la propiedad
Para entender la referencia Fuerte y Débil, considere el siguiente ejemplo, supongamos que tenemos un método llamado como displayLocalVariable.
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
}
En el método anterior, el alcance de la variable myName se limita al método displayLocalVariable, una vez que el método finaliza, la variable myName que contiene la cadena "ABC" se desasignará de la memoria.
Y ahora, si queremos mantener el valor de la variable myName a lo largo de nuestro ciclo de vida del controlador de vista. Para esto podemos crear la propiedad nombrada como nombre de usuario que tendrá una referencia fuerte a la variable myName (ver self.username = myName;
en el siguiente código), como se muestra a continuación,
@interface LoginViewController ()
@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;
- (void)displayLocalVariable;
@end
@implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[self displayLocalVariable];
}
- (void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
Ahora, en el código anterior puede ver que myName se ha asignado a self.username y self.username tiene una referencia segura (como hemos declarado en la interfaz usando @property) a myName (indirectamente tiene una referencia fuerte a la cadena "ABC"). Por lo tanto, String myName no se desasignará de la memoria hasta que self.username esté vivo.
- Referencia débil
Ahora considere asignar myName a dummyName, que es una referencia débil, self.dummyName = myName; A diferencia de la referencia fuerte, Débil mantendrá mi nombre solo hasta que haya una referencia fuerte a mi nombre. Vea el código de abajo para entender la referencia débil,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}
En el código anterior hay una referencia débil a myName (es decir, self.dummyName tiene una referencia débil a myName) pero no hay una referencia fuerte a myName, por lo que self.dummyName no podrá mantener el valor de myName.
Ahora nuevamente considere el siguiente código,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
self.dummyName = myName;
}
En el código anterior, self.username tiene una referencia fuerte a myName, por lo que self.dummyName ahora tendrá un valor de myName incluso después de que el método termine, ya que myName tiene una referencia fuerte asociada.
Ahora, cada vez que hacemos una referencia fuerte a una variable, su conteo de retención se incrementa en uno y la variable no se asigna a cero.
Espero que esto ayude.
Por lo que sé, strong
y retain
son sinónimos, por lo que hacen exactamente lo mismo.
Entonces el weak
es casi como assign
, pero automáticamente establecido en nulo después de que el objeto al que apunta se desasigna.
Eso significa que, simplemente puede reemplazarlos.
Sin embargo , hay un caso especial que he encontrado, donde tuve que usar assign
, en lugar de weak
. Digamos que tenemos dos propiedades delegateAssign
y delegateWeak
. En ambos está almacenado nuestro delegado, que nos posee al tener la única referencia fuerte. El delegado está desasignado, por lo que -dealloc
se llama a nuestro método -dealloc
.
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething];
[delegateAssign doSomething];
}
El delegado ya está en proceso de desasignación, pero aún no está completamente desasignado. ¡El problema es que weak
referencias weak
a él ya están anuladas! La propiedad delegateWeak
contiene nil, pero delegateAssign
contiene un objeto válido (con todas las propiedades ya publicadas y anuladas, pero sigue siendo válida).
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething]; // Does nothing, already nil.
[delegateAssign doSomething]; // Successful call.
}
Es un caso bastante especial, pero nos revela cómo funcionan esas variables weak
y cuándo se anulan.