11

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

@property (nonatomic, retain) NSNumber *consumption;

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

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

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

4

3 回答 3

4

您不能在@property()不修改编译器的情况下添加属性。

请注意,一般来说,@property完全不鼓励在运行时抓取声明的现有属性。运行时确实提供了一个 API,您可以通过它执行此操作,但它不适合通用用途,并且将来可能会发生变化。

于 2012-05-17T17:36:43.647 回答
0

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

有关这些 API 的信息,请参见此处。由于您需要更改编译器,因此这并不完全是您要查找的内容,而是一种将元数据添加到任何对象的方法。

于 2012-05-17T19:44:29.607 回答
0

向属性添加自定义属性并不常见,但我认为是可取的。此功能可用于自定义遍历类的属性。我在处理 SQL 时需要这个功能:如果我们有类似的属性:EXCLUDE_FROM_SELECT, INCLUDE_BY_INSERT, EXCLUDE_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(...);

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

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

@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:上面的编码不是确切的编码,它只是一个例子。而且我不确定最后一个宏解决方案是否有效,希望这会有所帮助。

于 2013-01-05T14:08:20.127 回答