2010-12-27 11 views
14

Siempre he pensado que no se puede declarar una propiedad de objeto en una categoría. Hasta que mi compañero lo hizo en el código de nuestra aplicación, y pareció funcionar.¿Desde cuándo es posible declarar las propiedades de Objective-C 2.0 en una categoría?

Me embarqué en un SO y en Google para tratar de explicarle que no, las categorías de Objective-C solo se pueden usar para agregar métodos, no propiedades. He encontrado a preguntas tales como:

Pero entonces me encontré this link en el sitio de Apple que contiene lo siguiente acerca de la declaración @property:

Una declaración de propiedad comienza con la palabra clave @property. @property puede aparecer en cualquier parte de la lista de declaración de método que se encuentra en @interface de una clase. @property puede aparecer también en la declaración de un protocolo o categoría. (Énfasis añadido)

Sé que esto no funciona:

@interface MyClass() 
NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

Pero esto compila:

@interface MyClass() 
@property NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

Mi pregunta es (a) ¿cuál es la mejor práctica aquí? y (b) ¿es algo nuevo en Objective-C 2.0 y, en lugar de utilizar un iVar "real", simplemente utiliza el almacenamiento asociativo entre bastidores para que funcione?

Respuesta

31

Siempre ha podido declarar un @property en una categoría. Lo que no pudo hacer, y todavía no puede, es declarar el almacenamiento de la propiedad en la categoría, ni como variable de instancia ni a través de `@synthesize.

Sin embargo ....

@interface MyClass() es no una categoría. Es una extensión de clase y tiene un papel claramente más específico que una categoría.

A saber, una extensión de clase se puede utilizar para extienden @interface de una clase, y esto incluye @properties que se pueden @synthesized (incluyendo la síntesis de almacenamiento en el tiempo de ejecución moderno).

Foo.h: 

@interface Foo 
@end 

Foo.m: 

@interface Foo() 
@property int x; 
@end 

@implementation Foo 
@synthesize x; // synthesizes methods & storage 
@end 

simplemente utiliza el almacenamiento asociativo entre bastidores para hacer este trabajo?

No, es una variable de instancia real. El tiempo de ejecución moderno corrige el problema de la clase base frágil.


@interface MyClass() 
NSInteger foobar; 
- (void) someCategorizedMethod; 
@end 

La anterior no funciona (como se esperaba), porque foobar es, efectivamente, una variable global.

Si lo cambia a:

@interface MyClass() { 
    NSInteger foobar; 
} 
- (void) someCategorizedMethod; 
@end 

Entonces que va a trabajar con la última versión del compilador LLVM (con las banderas correctas, tal como se indica en @Joshua un comentario).

+0

Para añadir a esto, su primer ejemplo en el que se añade un Ivar es perfectamente válido en llvm con -Xclang -fobjc-no frágiles-abi2 –

+1

Lo sería si estuviera agregando una Ivar. En ese caso, él está agregando una variable estática que no es una variable de instancia. – bbum

+0

gracias por la extensa explicación. ¡Compartiré este enlace con mis socios de codificación! – makdad

1

En general, las propiedades no son nada diferentes de otros métodos. Siempre que el ivar utilizado esté disponible en la clase ordinaria , no hay ningún problema. Es solo azúcar sintáctico.

Las cosas comienzan a ponerse más difíciles si también se crea automáticamente el ivar, como es posible en algunas configuraciones.

El punto principal aquí es que la declaración del ivar es independiente de la propiedad.

1

El almacenamiento de Assotiative es la solución. Echa un vistazo a este post.

+0

Gracias por el seguimiento: esta es una forma posible de solucionar este problema. – makdad

Cuestiones relacionadas