¿Las propiedades declaradas requieren una variable de instancia correspondiente?

101

¿Las propiedades en Objective-C 2.0 requieren que se declare una variable de instancia correspondiente? Por ejemplo, estoy acostumbrado a hacer algo como esto:

MyObject.h

@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

MyObject.m

@implementation
@synthesize name;
@end

Sin embargo, ¿qué pasa si hago esto en su lugar?

MyObject.h

@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end

¿Sigue esto siendo válido? ¿Y es de alguna manera diferente a mi ejemplo anterior?

indragie
fuente
¿Por qué el segundo 'MyObject.h' en negrita no es 'MyObject.m'?
Ríomhaire

Respuestas:

93

Si está utilizando Modern Objective-C Runtime (que es iOS 3.xo superior, o Snow Leopard de 64 bits o superior), entonces no necesita definir ivars para sus propiedades en casos como este.

Cuando tenga @synthesizela propiedad, el ivar se sintetizará también para usted. Esto evita el escenario "frágil-ivar". Puedes leer más sobre esto en Cocoa with Love

jbrennan
fuente
71

En su interfaz, puede declarar formalmente una variable de instancia entre las llaves, o por @propertyfuera de las llaves, o ambas. De cualquier manera, se convierten en atributos de la clase. La diferencia es que si declara @property, puede implementar using @synthesize, que codifica automáticamente su getter / setter por usted. El configurador del codificador automático inicializa enteros y flota a cero, por ejemplo. SI declara una variable de instancia y NO especifica una correspondiente @property, entonces no puede usar @synthesizey debe escribir su propio getter / setter.

Siempre puede anular el getter / setter codificado automáticamente especificando el suyo. Esto se hace comúnmente con la managedObjectContextpropiedad que se carga de forma diferida. Por lo tanto, declaras tu managedObjectContextcomo una propiedad, pero luego también escribes un -(NSManagedObjectContext *)managedObjectContextmétodo. Recuerde que un método, que tiene el mismo nombre que una variable de instancia / propiedad es el método "captador".

El @propertymétodo de declaración también le permite otras opciones, como retainy readonly, que el método de declaración de la variable de instancia no tiene. Básicamente, ivares la forma antigua, la @propertyamplía y la hace más elegante / fácil. Puede referirse a usar el self. prefijo, o no, no importa siempre que el nombre sea exclusivo de esa clase. De lo contrario, si su superclase tiene el mismo nombre de propiedad que usted, entonces debe decir como self.name o super.name para especificar de qué nombre está hablando.

Por lo tanto, verá cada vez menos personas declarando ivars entre las llaves y, en su lugar, cambiará a solo especificar @propertyy luego hacer @synthesize. No puede hacer @synthesizeen su implementación sin un correspondiente @property. El sintetizador solo sabe qué tipo de atributo es de la @propertyespecificación. La declaración de síntesis también le permite cambiar el nombre de las propiedades, de modo que pueda referirse a una propiedad por un nombre (abreviatura) dentro de su código, pero afuera en el archivo .h use el nombre completo. Sin embargo, con el autocompletado realmente genial que tiene XCode ahora, esto es una ventaja menor, pero sigue ahí.

Espero que esto ayude a aclarar toda la confusión y la desinformación que está flotando por ahí.

Papá Pitufo
fuente
Hoy en día no es obligatorio escribir @synthesize. Entonces, ¿cómo es válida esta respuesta en ese caso?
raaz
NO TIENES QUE declarar <code> @property ... @ Synthesize </code>. El uso de Synthesize le libera de tener que escribir un getter / setter en su implementación. Si no sintetiza, debe lanzar su propio getter / setter
PapaSmurf
2
@PapaSmurf Eso es incorrecto. Puede usarlos @property, no usarlos @synthesizey no implementarlos usted mismo. El compilador se auto- synthesizepara usted, sin tener que escribir eso más.
jbrennan
8

funciona en ambos sentidos, pero si no los declara entre llaves, no verá sus valores en el depurador en xcode.

Rickm
fuente
3

De la documentación:

En general, el comportamiento de las propiedades es idéntico en los tiempos de ejecución modernos y heredados (consulte "Versiones y plataformas en tiempo de ejecución" en la Guía de programación en tiempo de ejecución de Objective-C). Hay una diferencia clave: el tiempo de ejecución moderno admite la síntesis de variables de instancia, mientras que el tiempo de ejecución heredado no.

Para que @synthesize funcione en el tiempo de ejecución heredado, debe proporcionar una variable de instancia con el mismo nombre y tipo compatible de la propiedad o especificar otra variable de instancia existente en la instrucción @synthesize. Con el tiempo de ejecución moderno, si no proporciona una variable de instancia, el compilador agrega una por usted.

Charlie Elliott
fuente
3

Si está utilizando XCode 4.4 o posterior, generará código de síntesis de variable de instancia para usted.

Solo tienes que declarar propiedades como las siguientes; generará código de síntesis y variable de instancia declarando código para usted.

@property (nonatomic, strong) NSString *name;

generará código de síntesis como

@synthesize name = _name;

y puede acceder a la variable de instancia usando _name, es similar a declare

NSString* _name

pero si declaras una propiedad de solo lectura, es como

@property (nonatomic, strong, readonly) NSString *name;

generará código

@synthesize name;

o

@synthesize name = name; 

Por lo tanto, debe acceder al nombre de la variable instantánea sin el prefijo "_" de cualquier manera que pueda escribir su propio código de síntesis, luego el compilador generará el código para usted. puedes escribir

@synthesize name = _name;
Shafraz Buhary
fuente
1

El lenguaje de programación Objective-C: directivas de implementación de propiedades

Existen diferencias en el comportamiento de la síntesis de accesor que dependen del tiempo de ejecución (consulte también "Diferencia de tiempo de ejecución"):

  • Para los tiempos de ejecución heredados, las variables de instancia ya deben estar declaradas en el bloque @interface de la clase actual. Si existe una variable de instancia con el mismo nombre que la propiedad, y si su tipo es compatible con el tipo de la propiedad, se utiliza; de lo contrario, se obtiene un error de compilación.

  • Para los tiempos de ejecución modernos (consulte “Versiones y plataformas en tiempo de ejecución” en la Guía de programación en tiempo de ejecución de Objective-C), las variables de instancia se sintetizan según sea necesario. Si ya existe una variable de instancia con el mismo nombre, se utiliza.

Nate
fuente