我可以在Objective-C中为成员指定自定义属性吗?

时间:2012-05-17 16:58:59

标签: objective-c

当我声明一个属性时,我可以在声明中放入各种属性,这对编译器有特殊意义:

@property (nonatomic, retain) NSNumber *consumption;

此处,nonatomicretain是属性。是否可以添加自定义属性,并能够在运行时检查此属性的存在性?例如:

@property (nonatomic, retain, test) NSNumber* consumption;

我基本上使用的构造可以替代属性的使用,因为我从C#/ .NET中知道它们 - 所以也欢迎其他建议。

3 个答案:

答案 0 :(得分:4)

如果不修改编译器,则无法向@property()添加属性。

请注意,一般来说,在运行时甚至对@property声明的现有属性进行grubbing是非常不鼓励的。运行时确实提供了一个API,您可以通过它来执行此操作,但它不是用于通用目的,并且将来可能会更改。

答案 1 :(得分:0)

您始终可以将属性名称的NSDictionary添加到NSArray属性中。这可以存储在基类或通过objc_setAssociatedObjects和objc_getAssociatedObjects API与原始对象关联的单独类中。

有关这些API的信息,请参阅here。这不是你想要的,因为你需要更改编译器,但这是一种向任何对象添加元数据的方法。

答案 2 :(得分:0)

向属性添加自定义属性并不常见,但我认为这是可取的。此功能可用于自定义遍历类的属性。我在处理SQL时需要这个功能:如果我们有以下属性:EXCLUDE_FROM_SELECTINCLUDE_BY_INSERTEXCLUDE_FROM_UPDATE ...那么它会非常好。

实际上,我不确定是否有办法为@property指令启用它。但是,我们可能会做类似的事情:

如果您查看objc / runtime.h,您可以找到一个函数:class_replaceProperty,这在官方网站上没有记录。记录了一个名为class_addProperty的类似函数,可以帮助您理解前一个函数的参数。实际上,我认为@property使用这个函数来进行属性设置(但我不能证明它的确如此)。

您可能还需要以下功能:

void class_copyPropertyList(...);
void property_copyAttributeList(...);
void class_getProperty(...);

通过使用这些函数,您可以执行@property实际执行的操作。

我为之前的SQL问题所做的是定义3个函数来注册自定义属性:

void prepareClass(...);
void registerAttributes(...);
void endRegister(...);

然后我们可以在你的tagart类的+initialize函数中进行注册。

但是,使用代码(与简单的@interface + @property声明相比)可能不是您的最佳解决方案,因为我们可能希望直接从声明中查看属性设置。实际上,我们可以使用__attribute__((constructor))和宏:

来做得更好

@interface @end实际上允许你这样做:

@interface MyVO : NSObject
__attribute__((constructor))
void prepareForMyVO(){ prepareClass(MyVO);}
@property (strong) id p1;
__attribute__((constructor))
static void registerAttrForP1(){ registerAttributes("p1", EXCLUDE_FROM_SELECT);}
@property (strong) id p2;
__attribute__((constructor))
static void registerAttrForP2(){ registerAttributes("p2", INCLUDE_BY_INSERT);}
@end
__attribute__((constructor))
static void endRegisterForMyOV(){ endRegister();};

因此,您可以定义宏来处理此硬编码:

#define $p(clazz, zuper) class : zuper \
__attribute__((constructor)) static void prepareFor ## clazz(){ prepareClass(#MyVO);}
#define $r(p, attr) p; \
__attribute__((constructor)) static void registerAttrFor ## p(){ registerAttributes(#p, attr);}
#define $e(clazz) __attribute__((constructor)) static void endRegister ## clazz(){ endRegister();};



@interface $p(MyVO, NSObject)
@property (strong) id $r(p1, EXCLUDE_FROM_SELECT);
@property (strong) id $r(p1, INCLUDE_BY_INSERT);

@end $e(MyVO)

PS:上面的编码不是确切的编码,它只是一个例子。我不确定最后一个宏解决方案是否有效 希望这可以提供帮助。