@property retener, asignar, copiar, no atómico en Objective-C

Como alguien nuevo en Objective-C, ¿alguien me puede dar una visión general de la retención, asignación, copia y cualquier otra que me falta, que siguen la directiva @property? ¿Qué están haciendo y por qué querría usar uno sobre otro?

El artículo vinculado por MrMage ya no funciona. Entonces, esto es lo que aprendí en mi (muy) corto tiempo de encoding en Objective-C:

no atómico vs. atómico – “atómico” es el predeterminado. Siempre use “no atómico”. No sé por qué, pero el libro que leí dijo que “rara vez hay una razón” para usar “atómico”. (Por cierto: el libro que leí es el libro “Progtwigción de iOS” de BNR).

readwrite vs. readonly – “readwrite” es el predeterminado. Cuando @synthesize, tanto un getter como un setter se crearán para usted. Si usa “readonly”, no se creará ningún setter. Úselo para un valor que no quiera cambiar alguna vez después de la instanciación del objeto.

retener vs. copiar vs. asignar

  • “asignar” es el predeterminado. En el setter creado por @synthesize, el valor simplemente se asignará al atributo. Mi entendimiento es que “assign” debería usarse para atributos que no sean punteros.
  • “retener” es necesario cuando el atributo es un puntero a un objeto. El setter generado por @synthesize retendrá (es decir, agregará un conteo retenido) el objeto. Deberá liberar el objeto cuando haya terminado con él.
  • “copiar” es necesario cuando el objeto es mutable. Úselo si necesita el valor del objeto tal como está en este momento, y no desea que ese valor refleje los cambios realizados por otros propietarios del objeto. Tendrá que liberar el objeto cuando haya terminado con él porque está reteniendo la copia.

Antes de conocer los atributos de @property, debe saber de qué sirve @property.

  • @property ofrece una forma de definir la información que una clase pretende encapsular. Si declara un objeto / variable usando @property , ese objeto / variable será accesible para otras clases que importen su clase.

  • Si declara un objeto usando @property en el archivo de encabezado, debe sintetizarlo usando @synthesize en el archivo de implementación. Esto hace que el objeto KVC sea compatible . Por defecto, el comstackdor sintetizará los métodos de acceso para este objeto.

  • Los métodos de acceso son: setter y getter.

Ejemplo: .h

 @interface XYZClass : NSObject @property (nonatomic, retain) NSString *name; @end 

.metro

 @implementation XYZClass @synthesize name; @end 

Ahora el comstackdor sintetizará los métodos de acceso para el nombre .

 XYZClass *obj=[[XYZClass alloc]init]; NSString *name1=[obj name]; // get 'name' [obj setName:@"liza"]; // first letter of 'name' becomes capital in setter method 
  • Lista de atributos de @property

    atómico, no atómico, retener, copiar, solo leer, leer, asignar, fuerte, getter = método, setter = método, unsafe_unretained

  • atomic es el comportamiento predeterminado. Si un objeto se declara como atómico, se convierte en thread-safe. Thread-safe significa que, en un momento, solo un hilo de una instancia particular de esa clase puede tener el control sobre ese objeto.

Si el hilo está ejecutando el método getter, entonces otro hilo no puede ejecutar el método setter en ese objeto. Es lento.

 @property NSString *name; //by default atomic` @property (atomic)NSString *name; // explicitly declared atomic` 
  • no atómico no es seguro para subprocesos. Puede usar el atributo de propiedad no atómica para especificar que los descriptores de acceso sintetizados simplemente establezcan o devuelvan un valor directamente, sin garantías sobre lo que sucederá si se accede a ese mismo valor simultáneamente desde diferentes subprocesos.

Por esta razón, es más rápido acceder a una propiedad no atómica que a una atómica.

 @property (nonatomic)NSString *name; 
  • retener es obligatorio cuando el atributo es un puntero a un objeto.

El método setter boostá el recuento retenido del objeto, de modo que ocupe la memoria en el grupo de autorrelease.

 @property (retain)NSString *name; 
  • copiar Si usa copiar, no puede usar retener. El uso de una instancia de copia de la clase contendrá su propia copia.

Incluso si se establece una cadena mutable y luego se cambia, la instancia captura cualquier valor que tenga en el momento en que se establece. No se sintetizarán métodos setter y getter.

 @property (copy) NSString *name; 

ahora,

 NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"]; xyzObj.name = nameString; [nameString appendString:@"Pizza"]; 

nombre no se verá afectado.

  • readonly Si no desea permitir que se cambie la propiedad mediante el método setter, puede declarar la propiedad de solo lectura.

El comstackdor generará un getter, pero no un setter.

 @property (readonly) NSString *name; 
  • readwrite es el comportamiento predeterminado. No necesita especificar el atributo readwrite de forma explícita.

Es opuesto a readonly.

 @property (readwrite) NSString *name; 
  • assign generará un setter que asigna el valor a la variable de instancia directamente, en lugar de copiarlo o retenerlo. Esto es mejor para tipos primitivos como NSInteger y CGFloat, u objetos que no posee directamente, como los delegates.

Recuerde que retener y asignar son básicamente intercambiables cuando la recolección de basura está habilitada.

 @property (assign) NSInteger year; 
  • fuerte es un reemplazo para retener.

Viene con ARC.

 @property (nonatomic, strong) AVPlayer *player; 
  • getter = método Si desea utilizar un nombre diferente para un método getter, es posible especificar un nombre personalizado agregando atributos a la propiedad.

En el caso de propiedades booleanas (propiedades que tienen un valor SÍ o NO), es habitual que el método getter comience con la palabra “es”

 @property (getter=isFinished) BOOL finished; 
  • setter = método Si desea usar un nombre diferente para un método setter, es posible especificar un nombre personalizado agregando atributos a la propiedad.

El método debe terminar con dos puntos.

 @property(setter = boolBool:) BOOL finished; 
  • unsafe_unretained Hay algunas clases en Cocoa y Cocoa Touch que aún no admiten referencias débiles, lo que significa que no puede declarar una propiedad débil o una variable local débil para realizar un seguimiento de ellas. Estas clases incluyen NSTextView, NSFont y NSColorSpace, etc. Si necesita utilizar una referencia débil a una de estas clases, debe usar una referencia insegura.

Una referencia insegura es similar a una referencia débil ya que no mantiene vivo su objeto relacionado, pero no se establecerá en cero si el objeto de destino está desasignado.

 @property (unsafe_unretained) NSObject *unsafeProperty; 

Si necesita especificar múltiples atributos, simplemente inclúyalos como una lista separada por comas, como esta:

 @property (readonly, getter=isFinished) BOOL finished; 

Después de leer muchos artículos, decidí juntar toda la información de los atributos:

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

A continuación hay un enlace al artículo detallado donde puede encontrar estos atributos.

¡Muchas gracias a todas las personas que dan mejores respuestas aquí!

Atributos o atributos de propiedades variables en iOS

Aquí está la descripción de la muestra del artículo

  1. atómico Atómico significa que solo un hilo accede a la variable (tipo estático). -Atomic es seguro para subprocesos. -pero es lento en rendimiento -activo es el comportamiento predeterminado -Atner accessors en un entorno no basura (es decir, cuando se usa retener / liberar / liberar automáticamente) utilizará un locking para asegurarse de que otro subproceso no interfiere con la configuración / obtención correcta del valor -no es en realidad una palabra clave.

Ejemplo:

 @property (retain) NSString *name; @synthesize name; 
  1. no atómico -Natural significa acceso múltiple a la variable (tipo dynamic). -Natural es inseguro. -pero es rápido en rendimiento -Natural no es un comportamiento predeterminado, necesitamos agregar palabra clave no-atómica en el atributo de propiedad. -puede provocar un comportamiento inesperado, cuando dos procesos (hilos) diferentes acceden a la misma variable al mismo tiempo.

Ejemplo:

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

Explique:

Supongamos que hay una propiedad de cadena atómica llamada “nombre”, y si llama [self setName: @ “A”] desde el subproceso A, llame [self setName: @ “B”] desde el subproceso B y llame a [self name] desde hilo C, entonces toda la operación en hilo diferente se realizará en serie, lo que significa que si un hilo está ejecutando setter o getter, entonces otros hilos esperarán. Esto hace que la propiedad “nombre” de lectura / escritura sea segura, pero si otro hilo D llama a [nombre de lanzamiento] simultáneamente, entonces esta operación puede producir un locking porque no hay una llamada setter / getter involucrada aquí. Lo que significa que un objeto es de lectura / escritura segura (ATOMIC) pero no es seguro para subprocesos, ya que otros subprocesos pueden enviar simultáneamente cualquier tipo de mensajes al objeto. El desarrollador debe garantizar la seguridad del hilo para dichos objetos.

Si la propiedad “nombre” no fuera atómica, todos los hilos en el ejemplo anterior – A, B, C y D se ejecutarán simultáneamente produciendo cualquier resultado impredecible. En caso de atómica, cualquiera de A, B o C se ejecutará primero pero D aún puede ejecutar en paralelo.

  1. fuerte (iOS4 = retener) -dice “mantener esto en el montón hasta que no lo apunte más” -en otras palabras, “soy el propietario, no se puede traficar con esto 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 punteros fuertes. -Generalmente utilizamos strong para UIViewControllers (padres del elemento UI) -strong se usa con ARC y básicamente te ayuda, al no tener que preocuparte 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; 
  1. weak (iOS4 = unsafe_unretained): dice “keep this while while alguien lo señala 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 siempre que lo haga el objeto principal. -una referencia débil es una referencia que no protege el objeto referenciado de la recolección por un recolector de basura. -Weak 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).

  1. retain = strong -it se conserva, el valor anterior se libera y se asigna -retain especifica que se debe enviar el nuevo valor -retain on assignment y el valor anterior enviado -release -retain es igual que strong. -apple dice que si escribes retener, se convertirá automáticamente / funcionará solo como fuerte. -metodos como “alloc” incluyen un “retener” implícito

Ejemplo:

 @property (nonatomic, retain) NSString *name; @synthesize name; 
  1. assign -assign 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 -I usaría assign para propiedades primitivas C y weak para referencias débiles a objetos Objective-C.

Ejemplo:

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

    -unsafe_unretained es un calificador de propiedad que le dice a ARC cómo insertar las llamadas retener / liberar -unsafe_unretained es la versión ARC de assign.

Ejemplo:

 @property (nonatomic, unsafe_unretained) NSString *nickName; @synthesize nickName; 
  1. copia es necesaria cuando el objeto es mutable. -copy especifica que se debe enviar el nuevo valor -copy en la asignación y el valor anterior enviado -release. -copy es como retener devuelve un objeto que debe liberar explícitamente (por ejemplo, en dealloc) en entornos no recolectados. -si usa copia, aún necesita liberar eso en dealloc. -Utilice esto si necesita el valor del objeto tal como está en este momento, y no desea que ese valor refleje los cambios realizados por otros propietarios del objeto. Tendrá que liberar el objeto cuando haya terminado con él porque está reteniendo la copia.

Ejemplo:

 @property (nonatomic, copy) NSArray *myArray; @synthesize myArray; 

Se puede acceder a la propiedad atómica con solo un hilo a la vez. Es seguro para subprocesos . El valor predeterminado es atómico. Tenga en cuenta que no existe una palabra clave atómica

Nonatomic significa que múltiples hilos pueden acceder al artículo. Es inseguro.

Así que uno debe tener mucho cuidado al usar Atomic. Como esto afecta el rendimiento de su código