2010-11-24 15 views
26

Estoy atascado con las propiedades de Object-C. Lo que necesito es asignar una propiedad de solo escritura para una variable, exactamente lo opuesto a readonly, es decir, la variable puede tener setMethod, pero no debe tener getMethod. No sé cómo hacerlo. las respuestas con algunos fragmentos de código son apreciadas.Escribir solo propiedad en Objective-C

+2

¿De qué sirve la propiedad de solo escritura? En mi humilde opinión, es solo un desperdicio de memoria. – Eimantas

+20

Muchos de los usos; por lo general, cuando desea que algo sea públicamente de solo escritura e internamente a la clase es readwrite. – bbum

+0

Cuando una clase externa conoce una variable que se debe pasar, pero no tiene ninguna razón para saber en qué está configurado actualmente. – ArtOfWarfare

Respuesta

11

Usted puede hacer algo como:

@interface MyClass { 
@private 
int _var; 
} 

- (void)setVar:(int)newVar; 
@end 

@implementation MyClass 
- (void)setVar:(int)newVar { 
_var = newVar; 
} 
@end 

Ahora se puede acceder a la variable var como una propiedad que es de sólo escritura:

@implementation SomeOtherClass 
... 
MyClass c = [[MyClass alloc] init]; 
c.var = 3; 
... 
@end 

Y si se intenta leer la propiedad falsificar la el compilador te advertirá.

+1

Necesita definir un método '- (void) setVar: (int) newVar' en la implementación, así como en la interfaz. – JeremyP

+0

Tenga en cuenta que esto no oculta por completo el valor. A menos que anule (BOOL) accessInstanceVariablesDirectly con NO, puede obtener el valor con valueForKey: @ "var". E incluso si anula esto, aún puede obtener el valor con un método objC-runtime como object_getInstanceVariable. –

+4

no es una propiedad – kubbing

5

¿Hay alguna razón para que esto tenga que ser una propiedad? Simplemente declararía el setter como método y usaría la sintaxis normal [foo setVar:bar].

+5

O use la sintaxis de puntos ... 'foo.var = bar;' seguirá funcionando. – bbum

+0

Sí, eso funciona, pero xCode no parece autocompletar var cuando escribe. –

+0

@FredrikJohansson tienes razón. Para una solución amigable de autocompletar, es posible que desee verificar mi solución. –

44

Otro enfoque válido es declarar la propiedad normal y hacer que el comprador no está disponible

@interface MyClass 
@property NSString * var; 
- (NSString *)var UNAVAILABLE_ATTRIBUTE; 
@end 

Esto elevará un error en tiempo de compilación en caso de que alguien trata de acceder al comprador.


La principal ventaja de este enfoque es que en realidad tiene un bienes inmuebles TM y no un sustituto falsificado por una variable de instancia y un organismo, lo que implica que:

  • se Obtendrá la autocompletación cuando use notación de puntos en Xcode
  • todas las funciones de tiempo de ejecución como class_getProperty y class_copyPropertyList funcionarán como se esperaba.

Dicho esto, la aplicación captador se sintetiza de todos modos y se puede invocar usando algo como

NSString * string = [myObj performSelector:@selector(var)]; 

o el uso de NSInvocation (en caso de una propiedad no id)

Si está paranoico y usted Realmente desea evitar que el cliente invoque el captador, puede lanzar una excepción explícitamente al proporcionar su propia implementación.

@implementation MyClass 
- (int)var { 
    [NSException raise:NSInternalInconsistencyException 
       format:@"property is write-only"]; 
} 
@end 

De todos modos, si alguien quiere seriamente modificar el comportamiento variable de instancia, pueden utilizar el tiempo de ejecución para acceder a ella, por lo que la última precaución es probablemente inútil dado el caso de uso. Un error en tiempo de compilación es lo que realmente está buscando.

+0

¿está disponible para LLVM? – Mingming

+0

Esta debería ser la respuesta aceptada. – braden

Cuestiones relacionadas