¿Cuál es la visibilidad de las variables de instancia @synthesized?

Si tiene una propiedad en su interfaz pública como la siguiente

@interface MyClass : NSObject @property(strong) NSString *myProp; @end 

Y luego sintetizarlo, en efecto sintetizando la variable:

 @implementation MyClass @synthesize myProp = _myProp; // or just leave it at the default name.. @end 

¿Cuál es la visibilidad de la variable de instancia _myProp ? Es decir, ¿esto se considera @public , @protected o @private ? Supongo que, dado que MySubClass podría heredar de MyClass , también obtendría las propiedades (naturalmente), pero ¿también heredaría la visibilidad de la variable de instancia?

¿Qué diferencia hay si pongo la propiedad en una extensión de clase? Eso escondería la propiedad de las subclases, y supongo que la variable de instancia también. ¿Está esto documentado en algún lugar?

Un ivar sintetizado es completamente invisible para todo el código que no puede ver la línea @synthesize (lo que básicamente significa algo fuera del archivo .m). No está @protected , no es @private , es simplemente desconocido. Con un @private privado, a otro código que intente acceder se le informará que es privado, pero con un ivar sintetizado, a otro código que intente acceder se le informará que el campo simplemente no existe.

Como experimento mental, intente imaginar una situación en la que el ivar actuó como si estuviera @protected . Usted hace una subclase, y usted ensucia con el ivar allí. Ahora vuelves a la superclase y cambias @synthesize myProp a @synthesize myProp=foo . ¿Qué sucede en la subclase? Cuando el comstackdor procesa la subclase, no puede ver la línea @synthesize , por lo que no tendría idea de que acaba de cambiar el nombre del ivar. De hecho, ni siquiera puede decir si la propiedad está respaldada por un ivar en absoluto, o si se implementa con métodos de acceso escritos a medida. Espero que sea obvio por qué esto significa que la subclase no puede acceder al ivar, y tampoco a ninguna otra clase.

Dicho esto, no estoy seguro de qué hace el comstackdor si escribe código en el mismo archivo .m que intenta acceder al ivar. Espero que trate al ivar como @private (ya que el comstackdor puede, de hecho, ver que existe el ivar).

Además, nada de esto influye en los métodos de tiempo de ejecución. Otras clases todavía pueden usar los métodos de tiempo de ejecución obj-c para buscar dinámicamente la lista de ivar de la clase y rebuscar con ella.

Si se declara en su interfaz, es prácticamente público cuando se utiliza el declarativo @property . Si desea utilizar declaraciones @property y mantener su propiedad verdaderamente privada, debe crear una categoría privada en su implementación.

MyClass.h

 @interface MyClass : NSObject { @private NSObject* foo; } @end 

MyClass.m

 #import "ClassWithPrivateProperty.h" @interface MyClass () @property (nonatomic,retain) NSObject* foo; @end @implementation MyClass @synthesize foo; // class implementation... @end 

Una variable sintetizada actúa como si @private declarada @private :

 @interface Garble : NSObject @property (copy) NSString * s; @end @implementation Garble @synthesize s; @end @interface Bargle : Garble @end @implementation Bargle - (void) useS { NSLog(@"%@", s); // error: instance variable 's' is private } @end 

Juro que he visto esto en los documentos , pero no puedo encontrarlo ahora. Se actualizará si lo rastreo.

Puede crear una propiedad dinámica e indicarle al comstackdor que su instanciación estaría en tiempo de ejecución.

Y luego en tu subclase escribe tu propio getter o sintetiza la propiedad.

@interface BaseClass: NSObject

@property (no atómico, fuerte) NSString * ThisWillBeSynthesizedInRespectiveSubclasses;

@fin

@implementation BaseClass

@dynamic ThisWillBeSynthesizedInRespectiveSubclasses;

@fin

En Sub clases

@interface Subclase: BaseClass

@fin

@implementation Subclass @synthesize ThisWillBeSynthesizedInRespectiveSubclasses = _ThisWillBeSynthesizedInRespectiveSubclasses;

@fin

o escribes tus propios métodos setter / getter.

Espero que esto ayude !

Otras clases tienen acceso a todo lo que #include . En otras palabras, a todo lo que está dentro de tu encabezado.

Si algo aparece solo en su archivo de implementación, otras clases (incluidas las subclases) no saben que existe. Una propiedad sintetizada es así. Otras clases solo conocen la propiedad (una propiedad significa un método getter y un método setter) pero no saben nada sobre la implementación interna de sus métodos.

Tenga en cuenta que los especificadores de acceso (público / privado / protegido) en obj-c son solo una pista para el comstackdor de que, incluso si algo aparece en el archivo de encabezado, no se puede acceder. El tiempo de ejecución no lo verifica de ninguna manera.

¿Qué pasa si lo pones en una extensión de clase? Tenga en cuenta que una propiedad es un conjunto de dos métodos. Simplemente ocultas los métodos de cada clase, que incluye el encabezado principal de tu clase, pero no el encabezado de la extensión de clase.

Usamos esto, por ejemplo, para declarar una propiedad como de solo lectura y en la continuación de la clase lo declaramos como readwrite. Entonces, podemos usar el setter solo desde dentro de la clase.