2010-04-29 20 views
22

Estaba intentando crear una propiedad que sea de solo lectura. Quise inicializar con un valor de la clase que crea una instancia de esta clase, p.Inicializando una propiedad de solo lectura

@property (retain,readonly) NSString *firstName;

Y he intentado inicializar así:

-(id)initWithName:(NSString *)n{ self.firstName = n; }

Una vez que hice esto, el compilador informa de un error que la propiedad de sólo lectura no se puede asignar. Entonces, ¿cómo puedo hacer esto?

Respuesta

13

No utilice el colocador sintetizado:

firstName = [n retain]; //Or copy 

Se aconseja generalmente para eludir los setters en cualquiera de los métodos init y dealloc de todos modos.

+0

El problema con mi implementación anterior es que el valor no se conserva. Una vez que agregue el retener a la propiedad, esta asignación establecerá el valor en propiedad. Y si algún otro objeto accede a esta propiedad, este valor estará allí. También he modificado mi pregunta – awsome

+0

¿Por qué sería esto un problema? Usar 'firstname = [n retener]' hará que firstName sea un puntero a 'n'. Así que sí, cuando algún otro objeto acceda a esta propiedad, el valor estará allí. :) – Rengers

+0

Si trato de hacerlo de esta manera si tengo acceso a esta propiedad, recibo la siguiente excepción. Señal recibida del programa: "EXC_BAD_ACCESS". Y este error no se debe a ninguna otra propiedad. Investigué esto mucho en el depurador. Esta propiedad muestra "fuera del alcance". Y si lo asigno con, self.firstName = n;. entonces todo funciona bien – awsome

38

Asigne la variable de instancia directamente (no olvide agregar retain o copy si la necesita) o redeclare la propiedad en una extensión de clase privada. De esta manera:

En su archivo .h:

@property (readonly, copy) NSString *firstName; 

En el archivo .m:

@interface MyClass() 

// Redeclare property as readwrite 
@property (readwrite, copy) NSString *firstName; 

@end 


@implementation MyClass 

@synthesize firstName; 
... 

Ahora puede utilizar la incubadora sintetizado en su aplicación, pero el interfaz de la clase sigue mostrando el propiedad como solo lectura. Tenga en cuenta que otras clases que importan su archivo .h aún pueden llamar al -[MyClass setFirstName:], pero no sabrán que existe y obtendrán una advertencia del compilador.

+0

Esto parece una buena solución. Gracias. – awsome

+0

¿Hay alguna ventaja de usar el setter sintetizado vs. el enfoque sugerido por @Renger? – Madbreaks

2

Puede acceder directamente a la propiedad con:

_firstName = n;

El método de selección que implica self.firstName = n no se pueden sintetizar porque ha especificado readonly en @property (retain,readonly) NSString *firstName;, de ahí el error de compilación.

+0

no hay _firstName ... –

+0

entiendo que _firstName existirá. Es el ivar subyacente creado cuando se declara la propiedad. A partir de Xcode 4.6, el compilador debería crearlo automáticamente. – Bob9630

+0

Eso también lo entiendo @ Bob9630. Las otras respuestas a esta pregunta no produjeron el resultado deseado en mi caso, mientras que sí lo hicieron. –

Cuestiones relacionadas