2011-02-07 25 views
8

¿Se pueden crear atributos de propiedades personalizadas en Objective-C como en VB.NET? Por ejemplo, en VB.NET puede crear el atributo "Navegable" y leerlo en tiempo de ejecución para determinar si debe mostrar una propiedad o no.Atributos de propiedades personalizadas en Objective-c

Public Class Employee 
    <Browsable(True)> _ 
    Public Property Property1() As String 
     Get 

     End Get 
     Set(ByVal Value As String) 

     End Set 
    End Property 

    <Browsable(False)> _ 
    Public Property Property2() As String 
     Get 

     End Get 
     Set(ByVal Value As String) 

     End Set 
    End Property 
End Class 

me gustaría hacer lo mismo en Objective-C, incluso si es un atributo fijo que sólo pueden establecerse en tiempo de compilación y no se puede cambiar en absoluto.

Lo que trato de hacer es agregar un atributo a las propiedades de mi clase para determinar si las propiedades deben ser serializadas o no.

Conozco los atributos estándar de Objective-C (solo lectura, no atómicos, etc.), pero esos no me ayudan ... a menos que tenga una forma creativa de usarlos. También analicé el uso de atributos C con la palabra clave __attribute__(("Insert attribute here")), pero C tiene atributos específicos que sirven para fines específicos, y ni siquiera estoy seguro de que pueda leerlos en tiempo de ejecución. Si pierdo uno que pueda ayudarme, házmelo saber.

Intenté usar typdef. Por ejemplo:

typdef int serializableInt; 
serializableInt myInt; 

y usar la función de tiempo de ejecución property_getAttributes() Objective-C, pero todo lo que me dice es que myInt es un int. Supongo que typedef es bastante parecido a una macro en este caso ... a menos que pueda crear una variable de tipo serializableInt en tiempo de ejecución. De todos modos, aquí está Apple's documentation en los valores que obtienes de property_getAttributes().

El otro requisito es que este atributo tenga que funcionar con las subclases de NSObject y con los tipos de datos primitivos. Pensé en la idea de agregar a la clase una lista negra o una lista blanca como un ivar que me dijera qué propiedades omitir o serializar, que es básicamente la misma idea. Solo intento mover esa lista negra/blanca a los atributos para que sea fácil de entender cuando vea el archivo de encabezado de una clase, es consistente en todas las clases que creo y es menos propenso a errores.

Además, esto es algo a tener en cuenta. Realmente no necesito el atributo para tener un valor (VERDADERO o FALSO; 1, 2, 3 o lo que sea) porque el atributo en sí es el valor. Si el atributo existe, serializar; de lo contrario, omita.

Cualquier ayuda es apreciada. Si está seguro de que esto no es posible en Objective-C, hágamelo saber. Gracias.

+1

¿Qué hay de la creación de un método de clase que devuelve una matriz con el nombres de las variables de instancia serializables? –

+0

Pensé en eso y es una solución perfecta. Pero mi pregunta es específicamente sobre la resolución de este problema con atributos. ¿Incluso existen atributos personalizados en Objective-C? – Roberto

Respuesta

1

menos que he perdido su punto de ...

lo recomiendo declarar un protocolo. luego usar instancias de objetos objc como variables en sus clases objc que adoptan el protocolo.

@interface MONProtocol 

- (BOOL)isSerializable; 
- (BOOL)isBrowsable; 

/* ... */ 

@end 

@interface MONInteger : NSObject <MONProtocol> 
{ 
    int value; 
} 

- (id)initWithInt:(int)anInt; 

@end 

@interface MONIntegerWithDynamicProperties : NSObject <MONProtocol> 
{ 
    int value; 
    BOOL isSerializable; 
    BOOL isBrowsable; 
} 

- (id)initWithInt:(int)anInt isSerializable:(BOOL)isSerializable isBrowsable:(BOOL)isBrowsable; 

@end 

// finally, a usage 
@interface MONObjectWithProperties : NSObject 
{ 
    MONInteger * ivarOne; 
    MONIntegerWithDynamicProperties * ivarTwo; 
} 

@end 

si quiere compartir alguna implementación, entonces solo subclase NSObject y amplíe la clase base.

, entonces tendría que escribir algunas variantes para los tipos/estructuras que desea representar.

+0

Creo que te has perdido su punto.No quiere decir que el objeto sea navegable o serializable, pero que una propiedad dentro del objeto sea serializable o navegable. –

+0

@ncipollina no hay ningún atributo de propiedad, por lo que recomendé la composición. – justin

0

Me he encontrado con un problema similar al serializar objetos. Mi solución es agregar un @property (nonatomic, readonly) NSArray *serialProperties; que tiene un getter personalizado que devuelve los nombres (como NSString *) de las propiedades de esta (sub- clase) que deben ser serializadas.

Por ejemplo:

- (NSArray *)serialProperties { 
    return @[@"id", @"lastModified", @"version", @"uid"]; 
} 

O en una subclase:

- (NSArray *)serialProperties { 
    NSMutableArray *sp = [super serialProperties].mutableCopy; 
    [sp addObject:@"visibleName"]; 
    return sp; 
} 

A continuación, puede llegar fácilmente a todas las propiedades y sus valores a través de [self dictionaryWithValuesForKeys:self.serialProperties].

+0

@Bavarious ya hizo esta proposición en los comentarios, aunque usó un método de clase que es un enfoque más común para resolver esto. Roberto declaró explícitamente que la pregunta es sobre los "atributos" personalizados en las propiedades. –

+0

Lo siento, me he perdido ese comentario. Tal vez mis fragmentos todavía pueden ser útiles;) Sin embargo, AFAIK no hay nada como "atributos" en Objectivo-c. –

+0

Bueno, las propiedades tienen atributos en el tiempo de ejecución objc (como readonly, atomic, dynamic, weak, ...). Esos atributos se pueden consultar, pero no son extensibles. –

1

La deficiencia con las otras respuestas que he visto hasta ahora es que están implementadas como métodos de instancia, es decir, necesita tener una instancia antes de poder consultar estos metadatos. Probablemente hay EDGE casos en que sea apropiado, pero los metadatos acerca de las clases deben aplicarse como métodos de clase, tal como lo hace Apple, por ejemplo:

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key { } 

nos podemos imaginar nuestro propio a lo largo de líneas similares:

+ (BOOL)keyIsBrowsable:(NSString*)key { } 

o

+ (NSArray*)serializableProperties { } 

Imaginemos nuestra clase se llama FOOBar, y queremos saber si la clave es baz browsabl mi. Sin tener que crear un FOOBar sólo puede decir:

if ([FOOBar keyIsBrowsable:@"baz"]} { ... } 

Usted puede hacer casi cualquier cosa con esta técnica que se pueden hacer con los atributos personalizados. (Excepto por cosas como el atributo Serializable que requieren la cooperación del compilador, IIRC). Sin embargo, lo bueno de los atributos personalizados es que es fácil distinguir de un vistazo qué son los metadatos y qué es intrínseco a la funcionalidad real de esa clase, pero creo que eso es una ganancia menor.

(Por supuesto, es posible que deba verificar la existencia del selector keyIsBrowsable:, del mismo modo que debe comprobar la existencia de un atributo personalizado específico. De nuevo, los atributos personalizados tienen una ligera ventaja aquí, ya que podemos decirle al .NET runtime que nos las dé todas.)

0

No se pueden agregar propiedades personalizadas que no sean las que sdk ha proporcionado. . Pero hay un trabajo en torno a lograr su objetivo ...

@interface classTest:NSObject 

    @property(strong,nonatomic)NSString *firstName; 

    @property(strong,nonatomic)NSString *lastName; 

    @property(strong,nonatomic)NSMutableDictionary *metaData; 

@end 
@implementation classTest 

- (id) init 
{ 

self = [super init]; 
//Add meta data 
    metaData=[[NSmutableDictionary alloc]init]; 

    // 
    if(!self) return nil; 
    return self; 
} 

@end 

a fin de utilizar el diccionario para agregar y recuperar los metadatos ...

espero que ayude ....

1

Si desea agregar un atributo a la propiedad, clase, método o ivar, puede intentar usar github.com/libObjCAttr. Es muy fácil de usar, agregarlo a través cocoapods, y luego se puede añadir el atributo de esa manera:

@interface Foo 

RF_ATTRIBUTE(YourAttributeClass, property1 = value1) 
@property id bar; 

@end 

Y en el código:

YourAttributeClass *attribute = [NSDate RF_attributeForProperty:@"bar" withAttributeType:[YourAttributeClass class]]; 
// Do whatever you want with attribute, nil if no attribute with specified class 
NSLog(@"%@", attribute.property1) 
Cuestiones relacionadas