@property retiene, asigna, copia, no atómico en Objective-C
Como alguien nuevo en Objective-C, ¿alguien puede darme una descripción general de retener, asignar, copiar y cualquier otro que me falta y que sigue la directiva @property? ¿Qué están haciendo y por qué querría usar uno sobre otro?
Antes de conocer los atributos de @property, debes saber para qué sirve @property.
@property ofrece una manera de definir la información que una clase debe encapsular. Si declara un objeto/variable usando @property , entonces ese objeto/variable será accesible para otras clases que importen su clase.
Si declara un objeto usando @property en el archivo de encabezado, entonces debe sintetizarlo usando @synthesize en el archivo de implementación. Esto hace que el objeto sea compatible con KVC . De forma predeterminada, el compilador 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 compilador sintetizará los métodos de acceso para 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 lectura, leer y escribir, asignar, fuerte, getter=método, setter=método, unsafe_unretained
atómico es el comportamiento predeterminado. Si un objeto se declara como atómico, se vuelve seguro para subprocesos. Seguro para subprocesos significa que, a la vez, solo un subproceso de una instancia particular de esa clase puede tener control sobre ese objeto.
Si el subproceso realiza el método getter, otro subproceso no puede realizar el método setter en ese objeto. Es lento.
@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
- nonatomic no es seguro para subprocesos. Puede utilizar 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;
- Se requiere retención cuando el atributo es un puntero a un objeto.
El método de establecimiento aumentará el recuento de retención del objeto, de modo que ocupará memoria en el grupo de liberación automática.
@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 se cambia posteriormente, 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"];
El nombre no se verá afectado.
- solo lectura Si no desea permitir que la propiedad se cambie mediante el método de establecimiento, puede declarar la propiedad de solo lectura.
El compilador generará un captador, pero no un definidor.
@property (readonly) NSString *name;
- leer y escribir es el comportamiento predeterminado. No es necesario especificar explícitamente el atributo de lectura y escritura.
Es lo opuesto a solo lectura.
@property (readwrite) NSString *name;
- asignar generará un definidor 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 son de su propiedad directamente, como los delegados.
Tenga en cuenta que retener y asignar son básicamente intercambiables cuando la recolección de basura está habilitada.
@property (assign) NSInteger year;
- strong es un reemplazo de retener.
Viene con ARCO.
@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 “is”
@property (getter=isFinished) BOOL finished;
- setter=método Si desea utilizar un nombre diferente para un método de establecimiento, 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 se 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 utilizar una referencia insegura.
Una referencia insegura es similar a una referencia débil en el sentido de que no mantiene vivo su objeto relacionado, pero no se establecerá en nulo si se desasigna el objeto de destino.
@property (unsafe_unretained) NSObject *unsafeProperty;
Si necesita especificar varios atributos, simplemente inclúyalos como una lista separada por comas, como esta:
@property (readonly, getter=isFinished) BOOL finished;
El artículo vinculado por MrMage ya no funciona. Entonces, esto es lo que he aprendido en mi (muy) corto tiempo codificando en Objective-C:
no atómico versus atómico: "atómico" es el valor predeterminado. Utilice siempre "no atómico". No sé por qué, pero el libro que leí decía que "rara vez hay una razón" para usar "atómico". (Por cierto: el libro que leí es el libro "Programación de iOS" de BNR).
lectura y escritura versus solo lectura: "lectura y escritura" es el valor predeterminado. Cuando @synthesize, se crearán un captador y un definidor. Si utiliza "solo lectura", no se creará ningún configurador. Úselo para un valor que no desea cambiar nunca después de la instanciación del objeto.
retener versus copiar versus asignar
- "asignar" es el valor predeterminado. En el definidor creado por @synthesize, el valor simplemente se asignará al atributo. Tengo entendido que "asignar" debe usarse para atributos que no sean de puntero.
- "retener" es necesario cuando el atributo es un puntero a un objeto. El configurador generado por @synthesize retendrá (también conocido como agregará un recuento de retención) el objeto. Deberá soltar el objeto cuando haya terminado con él.
- Se necesita "copiar" 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 ningún cambio realizado por otros propietarios del objeto. Deberá liberar el objeto cuando haya terminado con él porque está conservando la copia.
Después de leer muchos artículos decidí juntar toda la información de los atributos:
- atómico //predeterminado
- no atómico
- fuerte=retener //predeterminado
- débil = inseguro_no retenido
- retener
- asignar //predeterminado
- inseguro_no retenido
- Copiar
- solo lectura
- leer escribir //predeterminado
A continuación se muestra un enlace al artículo detallado donde puede encontrar estos atributos.
¡¡Muchas gracias a todas las personas que dan mejores respuestas aquí!!
Atributos de propiedad variable o modificadores en iOS
Aquí está la descripción de muestra del artículo.
- atomic -Atomic significa que solo un hilo accede a la variable (tipo estático). -Atomic es seguro para subprocesos. -pero su rendimiento es lento -atómico es el comportamiento predeterminado -Los usuarios de acceso atómicos en un entorno sin recolección de basura (es decir, cuando se usa retener/liberar/liberar automáticamente) usarán un bloqueo para garantizar que otro subproceso no interfiera con la configuración/obtención correcta del valor. -En realidad no es una palabra clave.
Ejemplo :
@property (retain) NSString *name;
@synthesize name;
- nonatomic -Nonatomic significa que varios subprocesos acceden a la variable (tipo dinámico). -Nonatomic no es seguro para subprocesos. -pero tiene un rendimiento rápido -Nonatomic NO es un comportamiento predeterminado, necesitamos agregar una palabra clave noatómica en el atributo de propiedad. -Puede resultar en un comportamiento inesperado cuando dos procesos (hilos) diferentes acceden a la misma variable al mismo tiempo.
Ejemplo:
@property (nonatomic, retain) NSString *name;
@synthesize name;
Explicar:
Supongamos que hay una propiedad de cadena atómica llamada "nombre", y si llama a [self setName:@"A"] desde el hilo A, llama a [self setName:@"B"] desde el hilo B y llama a [self name] desde subproceso C, entonces todas las operaciones en subprocesos diferentes se realizarán en serie, lo que significa que si un subproceso está ejecutando setter o getter, otros subprocesos esperarán. Esto hace que la propiedad "nombre" sea segura en lectura/escritura, pero si otro subproceso D llama a [versión de nombre] simultáneamente, esta operación podría producir un bloqueo porque no hay ninguna llamada de establecimiento/obtención involucrada aquí. Lo que significa que un objeto es seguro para lectura/escritura (ATOMIC), pero no es seguro para subprocesos, ya que otros subprocesos pueden enviar simultáneamente cualquier tipo de mensaje al objeto. El desarrollador debe garantizar la seguridad de los subprocesos para dichos objetos.
Si la propiedad "nombre" no era atómica, entonces todos los subprocesos del ejemplo anterior: A, B, C y D se ejecutarán simultáneamente produciendo cualquier resultado impredecible. En el caso de atómico, cualquiera de A, B o C se ejecutará primero, pero D aún puede ejecutarse en paralelo.
- fuerte (iOS4 = retener) -dice "mantener 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. -Por defecto, todas las variables de instancia y las variables locales son indicadores fuertes. -Generalmente usamos strong para UIViewControllers (padres de elementos de UI). -strong se usa con ARC y básicamente le ayuda al no tener que preocuparse 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;
- débil (iOS4 = unsafe_unretained) -dice "conservar esto mientras alguien más lo indique firmemente" -lo mismo que asignar, no retener ni liberar -Una referencia "débil" es una referencia que no se retiene. -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).
- 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 una "retención" implícita
Ejemplo:
@property (nonatomic, retain) NSString *name;
@synthesize name;
- asignar -assign es el valor predeterminado y simplemente realiza una asignación de variable -assign 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;
inseguro_no retenido
-unsafe_unretained es un calificador de propiedad que le dice a ARC cómo insertar llamadas de retención/liberación. -unsafe_unretained es la versión ARC de asignar.
Ejemplo:
@property (nonatomic, unsafe_unretained) NSString *nickName;
@synthesize nickName;
- copiar -copiar es necesario cuando el objeto es mutable. -copiar especifica que se debe enviar el nuevo valor -copiar en la asignación y enviar el valor anterior -liberar. -copy es como retener devuelve un objeto que debes liberar explícitamente (por ejemplo, en dealloc) en entornos sin recolección de basura. -Si usas una copia, aún necesitas publicarla en dealloc. -Utilice esto si necesita el valor del objeto tal como está en este momento y no desea que ese valor refleje ningún cambio realizado por otros propietarios del objeto. Deberá liberar el objeto cuando haya terminado con él porque está conservando la copia.
Ejemplo:
@property (nonatomic, copy) NSArray *myArray;
@synthesize myArray;
Solo un hilo a la vez puede acceder a la propiedad atómica. Es seguro para subprocesos . El valor predeterminado es atómico. Tenga en cuenta que no hay ninguna palabra clave atómica.
No atómico significa que varios subprocesos pueden acceder al elemento. No es seguro para subprocesos
Por lo tanto, uno debe tener mucho cuidado al usar atomic, ya que afecta el rendimiento de su código.