Objective-C ARC: fuerte versus retener y débil versus asignar
Hay dos nuevos atributos de administración de memoria para las propiedades introducidas por ARC strong
y weak
.
Aparte de copy
que obviamente es algo completamente diferente, ¿ hay alguna diferencia entre strong
vs retain
y weak
vs assign
?
Según tengo entendido, la única diferencia aquí es que weak
se asignará nil
al puntero, mientras que assign
no, lo que significa que el programa fallará cuando envíe un mensaje al puntero una vez que se haya liberado. Pero si uso weak
, esto nunca sucederá, porque enviar un mensaje a nil
no hará nada.
No conozco ninguna diferencia entre strong
y retain
.
¿Hay alguna razón por la que debería usar assign
y retain
en proyectos nuevos, o este tipo de uso está en desuso?
Después de leer tantos artículos, publicaciones de Stackoverflow y aplicaciones de demostración para verificar los atributos de propiedades variables, decidí reunir toda la información de los atributos:
- atómico //predeterminado
- no atómico
- fuerte=retener //predeterminado
- débil
- retener
- asignar //predeterminado
- inseguro_no retenido
- Copiar
- solo lectura
- leer escribir //predeterminado
A continuación se muestra el enlace del artículo detallado donde puede encontrar todos los atributos mencionados anteriormente, que definitivamente lo ayudarán. ¡¡Muchas gracias a todas las personas que dan mejores respuestas aquí!!
Atributos de propiedad variable o modificadores en iOS
1.fuerte (iOS4 = retener)
- dice "mantén esto en el montón hasta que ya no lo señale"
- en otras palabras "Soy el propietario, no puedes desasignar esto antes de apuntar bien con lo mismo que retener"
- Utilice fuerte sólo si necesita retener el objeto.
- De forma predeterminada, todas las variables de instancia y las variables locales son indicadores sólidos.
- Generalmente usamos strong para UIViewControllers (padres de elementos de UI)
- strong se usa con ARC y básicamente te ayuda al no tener que preocuparte por el recuento de retención de un objeto. ARC lo libera automáticamente cuando haya terminado con él. Usar la palabra clave fuerte significa que usted es dueño del objeto.
Ejemplo:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.débil -
- dice "mantén esto mientras alguien más lo indique fuertemente"
- lo mismo que asignar, no retener ni liberar
- Una referencia "débil" es una referencia que no se conserva.
- Generalmente usamos débil para IBOutlets (Niños de UIViewController). Esto funciona porque el objeto secundario solo necesita existir mientras exista 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 se desasigna el objeto, el puntero débil se establece automáticamente en cero
Ejemplo :
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
Explicación fuerte y débil, gracias a BJ Homer :
Imagine que nuestro objeto es un perro y que el perro quiere huir (ser desasignado).
Los consejos fuertes son como una correa para el perro. Mientras tengas la correa atada al perro, este no se escapará. Si cinco personas atan su correa a un perro (cinco fuertes indicaciones para un objeto), entonces el perro no huirá hasta que se suelten las cinco correas.
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é atado, los niños pequeños aún podrán verlo y seguirán señalándolo. 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 será desasignado y todos los punteros débiles se pondrán a cero.
¿Cuándo usamos débil?
El único momento en el que querrías usar débil es si quisieras evitar los ciclos de retención (por ejemplo, el padre retiene al niño y el niño retiene al padre para que ninguno de los dos sea liberado).
3.retener = fuerte
- se retiene, el valor anterior se libera y se asigna retener especifica que se debe enviar el nuevo valor
- retener en la asignación y el valor anterior enviado -liberar
- retener es lo mismo que fuerte.
- Apple dice que si escribes retener, se convertirá automáticamente/funcionará solo como fuerte.
- métodos como "alloc" incluyen un "retain" implícito
Ejemplo:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.asignar
- asignar es el valor 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 definidor de la propiedad.
- Usaría asignar para propiedades primitivas de C y débil para referencias débiles a objetos Objective-C.
Ejemplo:
@property (nonatomic, assign) NSString *address;
@synthesize address;
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;
Es strong
lo mismo que retain
en una declaración de propiedad.
Para proyectos ARC usaría strong
en lugar de retain
, lo usaría assign
para propiedades primitivas de C y weak
para referencias débiles a objetos Objective-C.
no atómico/atómico
- No atómico es mucho más rápido que atómico.
- Utilice siempre no atómico a menos que tenga un requisito muy específico para atómico, lo cual debería ser poco común (atómico no garantiza la seguridad de los subprocesos; solo detiene el acceso a la propiedad cuando otro subproceso la establece simultáneamente)
fuerte/débil/asignar
- use fuerte para retener objetos; aunque la palabra clave retener es sinónima, es mejor usar fuerte en su lugar
- use débil si solo desea un puntero al objeto sin retenerlo - útil para evitar ciclos de retención (es decir, delegados) - automáticamente anulará el puntero cuando se libere el objeto
- use asignar para primitivas - exactamente igual que débil excepto que no anula el objeto cuando se libera (configurado de forma predeterminada)
(Opcional)
Copiar
- Úselo para crear una copia superficial del objeto.
- Es una buena práctica establecer siempre propiedades inmutables para copiar: debido a que las versiones mutables se pueden pasar a propiedades inmutables, la copia garantizará que siempre estará tratando 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 getter cambiando la variable directamente a través de su variable de instancia o dentro del método getter mismo.
Hasta donde yo sé, strong
y retain
son sinónimos, hacen exactamente lo mismo.
Entonces weak
es casi como assign
, pero se establece automáticamente en nil después de que se desasigna el objeto al que apunta.
Eso significa que puedes simplemente reemplazarlos.
Sin embargo , me he encontrado con un caso especial en el que tuve que usar assign
, en lugar de weak
. Digamos que tenemos dos propiedades delegateAssign
y delegateWeak
. En ambos se almacena nuestro delegado, que nos posee al tener la única referencia fuerte. El delegado está desasignando, por lo que -dealloc
también se llama a nuestro método.
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething];
[delegateAssign doSomething];
}
El delegado ya se encuentra en el proceso de desasignación, pero aún no se ha desasignado por completo. ¡El problema es que weak
las referencias a él ya están anuladas! La propiedad delegateWeak
contiene cero, pero delegateAssign
contiene un objeto válido (con todas las propiedades ya publicadas y anuladas, pero aún válidas).
// 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 weak
funcionan esas variables y cuándo se anulan.