当我声明一个属性时,我可以在声明中放入各种属性,这对编译器有特殊意义:
@property (nonatomic, retain) NSNumber *consumption;
此处,nonatomic
和retain
是属性。是否可以添加自定义属性,并能够在运行时检查此属性的存在性?例如:
@property (nonatomic, retain, test) NSNumber* consumption;
我基本上使用的构造可以替代属性的使用,因为我从C#/ .NET中知道它们 - 所以也欢迎其他建议。
答案 0 :(得分:4)
如果不修改编译器,则无法向@property()
添加属性。
请注意,一般来说,在运行时甚至对@property
声明的现有属性进行grubbing是非常不鼓励的。运行时确实提供了一个API,您可以通过它来执行此操作,但它不是用于通用目的,并且将来可能会更改。
答案 1 :(得分:0)
您始终可以将属性名称的NSDictionary添加到NSArray属性中。这可以存储在基类或通过objc_setAssociatedObjects和objc_getAssociatedObjects API与原始对象关联的单独类中。
有关这些API的信息,请参阅here。这不是你想要的,因为你需要更改编译器,但这是一种向任何对象添加元数据的方法。
答案 2 :(得分: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(...);
然后我们可以在你的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:上面的编码不是确切的编码,它只是一个例子。我不确定最后一个宏解决方案是否有效 希望这可以提供帮助。