Objective-C ARC: fuerte vs retener y débil vs asignar

Hay dos nuevos atributos de administración de memoria para las propiedades introducidas por ARC, strong y weak .

Además de la copy , que obviamente es algo completamente diferente, ¿hay alguna diferencia entre strong vs retain y weak vs assign ?

Según entiendo, la única diferencia aquí es que weak asignará nil al puntero, mientras que assign no lo hará, lo que significa que el progtwig se bloqueará cuando envíe un mensaje al puntero una vez que se haya liberado. Pero si uso weak , esto no sucederá nunca, porque el mensaje de enviar a nil no hará nada.

No sé sobre cualquier diferencia entre strong y retain .

¿Hay alguna razón por la que debería usar assign y retain en proyectos nuevos, o el tipo de obsolescencia es obsoleta?

Desde la Transición a las Notas de versión de ARC (el ejemplo en la sección de 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 statement de propiedad.

Para 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 Stackoverflow y aplicaciones de demostración para verificar los atributos de las propiedades de las variables, decidí juntar toda la información de los atributos:

  1. atómico // predeterminado
  2. no atómico
  3. fuerte = retener // predeterminado
  4. débiles
  5. conservar
  6. asignar // por defecto
  7. inseguro_unretenido
  8. dupdo
  9. solo lectura
  10. readwrite // predeterminado

Debajo está el enlace detallado del artículo donde puedes encontrar todos los atributos mencionados anteriormente, que definitivamente te ayudarán. ¡Muchas gracias a todas las personas que dan mejores respuestas aquí!

Atributos o atributos de propiedades variables en iOS

1.strong (iOS4 = retener)

  • dice “mantener esto en el montón hasta que no lo señale más”
  • en otras palabras, “soy el propietario, no puedes destrabarlo antes de apuntar bien con lo mismo que retener”
  • Usas fuerte solo si necesitas retener el objeto.
  • Por defecto, todas las variables de instancia y las variables locales son indicadores fuertes.
  • Generalmente utilizamos strong para UIViewControllers (padres del elemento de UI)
  • strong se usa con ARC y básicamente lo ayuda, al no tener que preocuparse por el conteo retenido de un objeto. ARC lo libera automáticamente cuando haya terminado con eso. Usar la palabra clave fuerte significa que usted es el propietario del objeto.

Ejemplo:

 @property (strong, nonatomic) ViewController *viewController; @synthesize viewController; 

2.weak

  • dice “mantener esto mientras alguien más lo señale fuertemente”
  • lo mismo que asignar, no retener o liberar
  • Una referencia “débil” es una referencia que no conservas.
  • En general, utilizamos weak para IBOutlets (UIViewController’s Childs). Esto funciona porque el objeto hijo solo necesita existir mientras el objeto padre lo haga.
  • una referencia débil es una referencia que no protege el objeto referenciado de la recolección por un recolector de basura.
  • Débil es esencialmente asignar, una propiedad no retenida. Excepto cuando el objeto está desasignado, 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 :

Imagina que nuestro objeto es un perro, y que el perro quiere huir (ser desasignado).

Los indicadores fuertes son como una correa en el perro. Mientras tengas la correa unida al perro, el perro no huirá. Si cinco personas unen su correa a un perro, (cinco punteros fuertes a un objeto), entonces el perro no escapará hasta que las cinco correas estén sueltas.

Los indicadores débiles, por otro lado, son como niños pequeños que señalan al perro y dicen “¡Mira, un perro!” Mientras el perro siga con la correa, los niños pequeños aún pueden ver al perro, y aún así lo señalarán. Sin embargo, tan pronto como todas las correas se separan, el perro huye sin importar cuántos niños pequeños lo señalen.

Tan pronto como el último puntero fuerte (correa) ya no apunta a un objeto, el objeto será desasignado, y todos los punteros débiles se pondrán a cero.

Cuando usamos débil?

El único momento en que desearía usar weak, es si desea evitar ciclos de retención (por ejemplo, el padre retiene al hijo y el hijo retiene al padre, por lo que ninguno de los dos se libera).

3.retener = fuerte

  • se retiene, el valor anterior se libera y se le asigna retener especifica que se debe enviar el nuevo valor
  • retener en la asignación y el viejo valor enviado -release
  • 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 “retener” implícito

Ejemplo:

 @property (nonatomic, retain) NSString *name; @synthesize name; 

4. asignar

  • Asignar es el predeterminado y simplemente realiza una asignación de variable
  • assign es un atributo de propiedad que le dice al comstackdor cómo sintetizar la implementación del setter de la propiedad
  • Utilizaría la asignación para propiedades primitivas C y débil para referencias débiles a objetos Objective-C.

Ejemplo:

 @property (nonatomic, assign) NSString *address; @synthesize address; 

Hasta donde yo sé, strong y retain son sinónimos, por lo que hacen exactamente lo mismo.

Entonces, el weak es casi como assign , pero se establece automáticamente en cero después de que el objeto, apunta hacia, se desasigna.

Eso significa que puedes simplemente 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 se almacena nuestro delegado, que nos posee al tener la única referencia fuerte. El delegado está deslocalizando, 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 todavía no se ha desasignado por completo. ¡El problema es que weak referencias weak a él ya están anuladas! Property delegateWeak contiene nil, pero delegateAssign contiene un objeto válido (con todas las propiedades ya publicadas y anuladas, pero sigue siendo válido).

 // 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 son anuladas.

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, que debería ser raro (atomic no garantiza la seguridad de subprocesos, solo los puestos que acceden a la propiedad cuando se establece simultáneamente por otro subproceso)

fuerte / débil / asignar

  • use strong para retener objetos: aunque la palabra clave retain es sinónimo, es mejor utilizar strong en lugar de
  • use weak si solo quiere un puntero al objeto sin retenerlo, útil para evitar retener ciclos (es decir, delegates) – automáticamente anulará el puntero cuando se libere el objeto
  • use assign for primatives – exactamente igual a weak excepto que no anula el objeto cuando se libera (establecido de manera predeterminada)

(Opcional)

dupdo

  • Úselo para crear una copia superficial del objeto
  • buena práctica para establecer siempre propiedades inmutables para copiar, ya que las versiones mutables se pueden pasar a propiedades inmutables, la copia asegura 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 desactivar la configuración de la propiedad (evita que el código se compile si hay una infracción)
  • puede cambiar lo entregado por el getter cambiando la variable directamente a través de su variable de instancia, o dentro del método getter

El documento de Clang sobre el conteo automático de referencias (ARC) de Objective-C explica claramente los modificadores y los calificadores de propiedad:

Hay cuatro calificadores de propiedad:

  • __ autoreleasing
  • __ fuerte
  • __ * unsafe_unretained *
  • __ débil

Un tipo no es trivialmente calificado por la propiedad si está calificado con __ autoreleasing , __ strong o __ weak .

Luego hay seis modificadores de propiedad para la propiedad declarada:

  • assign implica __ * unsafe_unretained * ownership.
  • la copia implica __ fuerte propiedad, así como el comportamiento habitual de la semántica de copia en el colocador.
  • 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 débil , estos modificadores están disponibles en modos que no son ARC.

En términos semánticos, los calificadores de propiedad tienen un significado diferente en las cinco operaciones administradas : Lectura, Asignación, Inicialización, Destrucción y Movimiento, en las que la mayoría de las veces solo nos importa 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 según la calificación:

  • Para __ objetos fuertes , el nuevo puntaje primero se retiene; segundo, el lvalue está cargado de semántica primitiva; tercero, el nuevo punto se almacena en el valor l con semántica primitiva; y finalmente, el viejo pointee es lanzado. Esto no se realiza atómicamente; la sincronización externa se debe usar para hacer esto seguro frente a cargas y tiendas 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 desasignación, en cuyo caso el lvalue se actualiza a un puntero nulo. Esto debe ejecutarse atómicamente con respecto a otras asignaciones al objeto, a leer desde el objeto y al lanzamiento final del nuevo punto.
  • Para objetos __ * unsafe_unretained *, el nuevo pointee se almacena en el valor l usando semántica primitiva.
  • Para __ objetos de autorrelleno , el nuevo pointee se conserva, se libera automáticamente y se almacena en el valor l usando semántica primitiva.

La otra diferencia en Lectura, Iniciación, Destrucción y Movimiento, consulte la Sección 4.2 Semántica en el documento .

Fuerte:

  • La propiedad no se destruirá, pero solo una vez que establezca la propiedad en cero se destruirá el objeto
  • Por defecto, todas las variables de instancia y las variables locales son indicadores fuertes.
  • Usas fuerte solo si necesitas retener el objeto.
  • Generalmente utilizamos strong para UIViewControllers (padres del elemento de UI)
  • IOS 4 (no ARC) que podemos usar Retain KeyWord
  • IOS 5 (ARC) Podemos usar palabras clave fuertes

Ejemplo: @property (strong, nonatomic) ViewController * viewController;

@synthesize viewController;

Débiles

Por defecto, automáticamente se obtiene y se establece en cero

  • Generalmente utilizamos weak para IBOutlets (UIViewController’s Childs) y delegamos
  • lo mismo que asignar, no retener o liberar

Ejemplo: @property (débil, no atómico) IBOutlet UIButton * myButton;

@synthesize myButton;

Las diferencias entre fuerte y retener:

  • En iOS4, fuerte es igual a retener
  • Significa que tienes el objeto y lo mantienes en el montón hasta que ya no lo apuntes
  • Si escribes retener, automáticamente funcionará igual de fuerte

Las diferencias entre débil y asignar:

  • Una referencia “débil” es una referencia que no conservas y la mantienes mientras alguien más la señale con fuerza.
  • Cuando el objeto es “desasignado”, el puntero débil se establece automáticamente en nulo
  • Un atributo de propiedad “assign” le dice al comstackdor cómo sintetizar la implementación del setter de la propiedad

strong, weak, assign atributos de propiedad definir cómo se gestionará la memoria para esa propiedad.

Fuerte significa que la cuenta de referencia se incrementará y la referencia a ella se mantendrá durante la vida del objeto

Débil (referencia no fuerte), significa que estamos apuntando a un objeto pero no aumentando su conteo de referencia. A menudo se usa cuando se crea una relación padre-hijo. El padre tiene una fuerte referencia al niño pero el niño solo tiene una referencia débil al padre.

Cada vez que se usa en var.
Cada vez que se usa en un tipo opcional.
Cambia automáticamente a sí mismo a cero.

Solo lectura , podemos establecer la propiedad inicialmente pero luego no se puede cambiar.

Copiar significa que estamos copiando el valor del objeto cuando se crea. También evita que su valor cambie.