cfi*_*her 41 cocoa properties objective-c objective-c-runtime
是否可以在运行时向Objective C对象添加属性?
小智 61
可以通过以下方式将正式属性添加到类中class_addProperty():
BOOL class_addProperty(Class cls,
const char *name,
const objc_property_attribute_t *attributes,
unsigned int attributeCount)
Run Code Online (Sandbox Code Playgroud)
前两个参数是不言自明的.第三个参数是属性的属性的阵列,并且每个属性特性是一个名称-值对,其遵循的Objective-C 型编码对声明的属性.请注意,文档仍然提到了用于编码属性属性的逗号分隔字符串.逗号分隔字符串中的每个段由一个objc_property_attribute_t实例表示.此外,objc_property_attribute_t除了泛型@类型编码之外,还接受类名id.
这是一个程序的初稿,它动态地将一个属性调用name给一个已经有一个名为的实例变量的类_privateName:
#include <objc/runtime.h>
#import <Foundation/Foundation.h>
@interface SomeClass : NSObject {
NSString *_privateName;
}
@end
@implementation SomeClass
- (id)init {
self = [super init];
if (self) _privateName = @"Steve";
return self;
}
@end
NSString *nameGetter(id self, SEL _cmd) {
Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName");
return object_getIvar(self, ivar);
}
void nameSetter(id self, SEL _cmd, NSString *newName) {
Ivar ivar = class_getInstanceVariable([SomeClass class], "_privateName");
id oldName = object_getIvar(self, ivar);
if (oldName != newName) object_setIvar(self, ivar, [newName copy]);
}
int main(void) {
@autoreleasepool {
objc_property_attribute_t type = { "T", "@\"NSString\"" };
objc_property_attribute_t ownership = { "C", "" }; // C = copy
objc_property_attribute_t backingivar = { "V", "_privateName" };
objc_property_attribute_t attrs[] = { type, ownership, backingivar };
class_addProperty([SomeClass class], "name", attrs, 3);
class_addMethod([SomeClass class], @selector(name), (IMP)nameGetter, "@@:");
class_addMethod([SomeClass class], @selector(setName:), (IMP)nameSetter, "v@:@");
id o = [SomeClass new];
NSLog(@"%@", [o name]);
[o setName:@"Jobs"];
NSLog(@"%@", [o name]);
}
}
Run Code Online (Sandbox Code Playgroud)
其(修剪)输出:
Steve
Jobs
Run Code Online (Sandbox Code Playgroud)
应该更仔细地编写getter和setter方法,但这应该足以作为如何在运行时动态添加形式属性的示例.
如果您查看此处NSKeyValueCoding记录的协议,您可以看到有一条消息称为:
- (id)valueForUndefinedKey:(NSString *)key
Run Code Online (Sandbox Code Playgroud)
您应该覆盖该方法,以便为指定的undefined属性提供自定义结果.当然,这假设您的类使用相应的协议.
这种方法通常用于向类提供未知行为(例如,不存在的选择器).
| 归档时间: |
|
| 查看次数: |
21418 次 |
| 最近记录: |