He declarado una propiedad de solo lectura en mi interfaz como tal:
@property (readonly, nonatomic, copy) NSString* eventDomain;
Tal vez no entiendo las propiedades, pero pensé que cuando lo declaras como readonly
, puedes usar el setter generado dentro del .m
archivo de implementación ( ), 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 intento usar el setter estándar o la sintaxis de puntos para establecer eventDomain
dentro de mi método init, me da un unrecognized selector sent to instance.
error. Por supuesto que estoy @synthesize
en la propiedad. Intentando usarlo así:
// inside one of my init methods
[self setEventDomain:@"someString"]; // unrecognized selector sent to instance error
Entonces, ¿estoy entendiendo mal la readonly
declaración de una propiedad? ¿O está pasando algo más?
.h
? De lo contrario, no veo cómo esto expondría a un setter público. GraciasEiko y otros dieron respuestas correctas.
He aquí una forma más sencilla: acceda 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:
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 características en Xcode 4.4 ), no necesita meterse con las tareas discutidas en las otras respuestas:
synthesize
palabra claveDespués de declarar una propiedad
foo
, se puede asumir Xcode ha añadido una variable miembro privada llamada con un prefijo de subrayado:_foo
.Si la propiedad fue declarada
readwrite
, Xcode genera un método getter llamadofoo
y un setter llamadosetFoo
. Estos métodos se llaman implícitamente cuando usa la notación de puntos (my Object.myMethod). Si la propiedad fue declaradareadonly
, no se genera ningún setter. Eso significa que la variable de respaldo, nombrada con el guión bajo, no es de solo lectura. Estoreadonly
significa simplemente que no se sintetizó ningún método de establecimiento y, por lo tanto, el uso de la notación de puntos para establecer un valor falla con un error del compilador. La notación de puntos falla porque el compilador le impide llamar a un método (el establecedor) que no existe.La forma más sencilla de evitar esto es acceder directamente a la variable miembro, nombrada con el guión bajo. ¡Puede hacerlo incluso sin declarar esa variable con el nombre de subrayado! 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 variable. Pero nunca ve esa declaración en su archivo de código fuente original. No magia, solo azúcar sintáctica .
El uso
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 autodocumente. Cuando ve elself->_foo
, sabe sin ambigüedad que_foo
es una variable miembro en esta instancia.Por cierto, la discusión sobre los pros y los contras de los accesores de propiedad versus el acceso directo a ivar es exactamente el tipo de tratamiento reflexivo que leerá en Dr. Matt Neuberg 's Programación iOS libro. Me resultó muy útil leer y releer.
fuente
readonly
para que ninguna otra clase pueda establecerla.Otra forma que he encontrado para trabajar con propiedades de solo lectura es usar @synthesize para especificar el almacén de respaldo. Por ejemplo
Luego en la implementación
Sus métodos pueden entonces establecerse
m_whatever
, ya que es una variable miembro.Otra cosa interesante de la que me he dado cuenta en los últimos días es que puede hacer propiedades de solo lectura que sean escribibles por subclases como tales:
(en el archivo de encabezado)
Luego, en la implementación
Utilizará la declaración en el archivo de encabezado, por lo que las subclases pueden actualizar el valor de la propiedad, mientras conservan su solo lectura.
Sin embargo, un poco lamentablemente en términos de ocultación y encapsulación de datos.
fuente
Consulte Personalización de clases existentes en los documentos de iOS.
Las propiedades de solo lectura solo tienen un método getter. Aún puede configurar el ivar de respaldo directamente dentro de la clase de la propiedad o usando la codificación de valor clave.
fuente
Está malinterpretando la otra pregunta. En esa pregunta hay una extensión de clase, declarada así:
Eso es lo que genera el setter solo visible dentro de la implementación de la clase. Entonces, como dice Eiko, debe declarar una extensión de clase y anular la declaración de propiedad para decirle al compilador que genere un establecedor solo dentro de la clase.
fuente
La solución más corta es:
MyClass.h
MyClass.h
fuente
Si una propiedad se define como de solo lectura, eso significa que efectivamente no habrá un definidor que pueda usarse internamente en la clase o externamente desde otras clases. (es decir, solo tendrá un "captador" si tiene sentido).
Por lo que parece, desea una propiedad de lectura / escritura normal que esté marcada como privada, lo que puede lograr configurando la variable de clase como privada en su archivo de interfaz como tal:
fuente