varias superponer studio lineas histogramas graficos graficas objective-c properties readonly

objective-c - studio - superponer graficas en r



¿Propiedades de solo lectura en Objective-C? (7)

He declarado una propiedad de solo lectura en mi interfaz como tal:

@property (readonly, nonatomic, copy) NSString* eventDomain;

Tal vez estoy malinterpretando las propiedades, pero pensé que cuando lo declaraste de manera que fuera de readonly , puedes usar el setter generado dentro del archivo de implementación ( .m ), pero las entidades externas no pueden cambiar el valor. Esta pregunta SO dice que eso es lo que debería suceder. Ese es el comportamiento que busco. Sin embargo, cuando trato de usar el setter estándar o la sintaxis de punto para establecer eventDomain dentro de mi método init, me da un unrecognized selector sent to instance. error. Por supuesto que estoy @synthesize la propiedad. Tratando de usarlo así:

// inside one of my init methods [self setEventDomain:@"someString"]; // unrecognized selector sent to instance error

Entonces, ¿estoy malinterpretando la declaración de readonly sobre una propiedad? ¿O algo más está pasando?


Consulte Personalización de clases existentes en los documentos de iOS.

readonly Indica que la propiedad es de solo lectura. Si especifica de solo lectura, solo se requiere un método getter en @implementation. Si usa @synthesize en el bloque de implementación, solo se sintetizará el método getter. Además, si intentas asignar un valor usando la sintaxis de punto, obtienes un error de compilación.

Las propiedades de solo lectura solo tienen un método getter. Todavía puede establecer el ivar de respaldo directamente dentro de la clase de la propiedad o usando la codificación del valor clave.


Eiko y otros dieron respuestas correctas.

Aquí hay una manera más simple: acceder directamente a la variable de miembro privado.

Ejemplo

En el archivo .h de encabezado:

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

En el archivo .m de implementación:

// inside one of my init methods self->_foo = @"someString"; // Notice the underscore prefix of var name.

Eso es todo, eso es todo lo que necesitas. Sin despeinarse sin problemas.

Detalles

A partir de Xcode 4.4 y LLVM Compiler 4.0 ( Nuevas funciones en Xcode 4.4 ), no necesita meterse con los quehaceres discutidos en las otras respuestas:

  • La palabra clave synthesize
  • Declarando una variable
  • Re-declarar la propiedad en el archivo .m de implementación.

Después de declarar un foo propiedad, puede suponer que Xcode ha agregado una variable miembro privada nombrada con un prefijo de guión bajo: _foo .

Si la propiedad fue declarada readwrite , Xcode genera un método getter llamado foo y un setter llamado setFoo . Estos métodos se invocan implícitamente cuando usa la notación de puntos (mi Object.myMethod). Si la propiedad fue declarada de readonly , no se genera setter. Eso significa que la variable de respaldo, nombrada con el guión bajo, no es de solo lectura. El readonly significa simplemente que no se sintetizó ningún método setter, y por lo tanto el uso de la notación de punto para establecer un valor falla con un error de compilación. La notación de punto falla porque el compilador le impide llamar a un método (el sistema) que no existe.

La forma más simple de evitar esto es acceder directamente a la variable miembro, nombrada con el guión bajo. ¡Puedes hacerlo incluso sin declarar esa variable con el guión bajo! Xcode está insertando esa declaración como parte del proceso de compilación / compilación, por lo que su código compilado tendrá la declaración de la variable. Pero nunca verá esa declaración en su archivo de código fuente original. No es magia, solo azúcar sintáctico .

Usar self-> es una forma de acceder a una variable miembro del objeto / instancia. Es posible que pueda omitir eso, y solo use el nombre var. Pero prefiero usar la flecha self + porque hace que mi código se auto-documente. Cuando veas el self->_foo , sabes sin ambigüedad que _foo es una variable miembro en esta instancia.

Por cierto, la discusión de los pros y los contras de los accesadores de propiedades versus el acceso directo a ivar es exactamente el tipo de tratamiento considerado que leerá en el libro de programación del Dr. Matt Neuberg para iOS . Me pareció muy útil leer y volver a leer.


Estás malinterpretando la otra pregunta. En esa pregunta hay una extensión de clase, declarada así:

@interface MYShapeEditorDocument () @property (readwrite, copy) NSArray *shapesInOrderBackToFront; @end

Eso es lo que genera al colocador solo visible dentro de la implementación de la clase. Entonces, como dice Eiko, necesitas declarar una extensión de clase y anular la declaración de propiedad para decirle al compilador que genere un setter solo dentro de la clase.


La solución más corta es:

MyClass.h

@interface MyClass { int myProperty; } @property (readonly) int myProperty; @end

MyClass.h

@implementation MyClass @synthesize myProperty; @end


Necesitas decirle al compilador que también quieres un setter. Una forma común es ponerlo en una extensión de clase en el archivo .m:

@interface YourClass () @property (nonatomic, copy) NSString* eventDomain; @end


Otra forma que he encontrado para trabajar con propiedades de solo lectura es usar @synthesize para especificar el almacén de respaldo. Por ejemplo

@interface MyClass @property (readonly) int whatever; @end

Luego en la implementación

@implementation MyClass @synthesize whatever = _whatever; @end

Sus métodos pueden establecer _whatever, ya que es una variable miembro.

Otra cosa interesante de la que me he dado cuenta en los últimos días es que puedes crear propiedades de solo lectura que se puedan escribir mediante subclases como las siguientes:

(en el archivo de encabezado)

@interface MyClass { @protected int _propertyBackingStore; } @property (readonly) int myProperty; @end

Luego, en la implementación

@synthesize myProperty = _propertyBackingStore;

Utilizará la declaración en el archivo de encabezado, por lo que las subclases pueden actualizar el valor de la propiedad, conservando su carácter de solo lectura.

Ligeramente lamentable en términos de ocultación de datos y encapsulamiento.


Si una propiedad se define como de solo lectura, eso significa que efectivamente no habrá un colocador que pueda usarse internamente para la clase o externamente de otras clases. (es decir: solo tendrá un "getter" si tiene sentido).

Por lo que dice, quiere una propiedad de lectura / escritura normal marcada como privada, que puede lograr estableciendo la variable de clase como privada en su archivo de interfaz como tal:

@private NSString* eventDomain; }