// C语言实现得getter
NSString *personNameGetter(id classInstance, SEL _cmd) {
Ivar ivar = class_getInstanceVariable([classInstance class], "_name");
return object_getIvar(classInstance, ivar);
}
// C语言实现得setter
void personNameSetter(id classInstance, SEL _cmd, NSString *newName) {
Ivar ivar = class_getInstanceVariable([classInstance class], "_name");
id oldName = object_getIvar(classInstance, ivar);
if (oldName != newName) object_setIvar(classInstance, ivar, [newName copy]);
}
//下面对应的编码值可以在官方文档里面找到
//编码值 含意
//c 代表char类型
//i 代表int类型
//s 代表short类型
//l 代表long类型,在64位处理器上也是按照32位处理
//q 代表long long类型
//C 代表unsigned char类型
//I 代表unsigned int类型
//S 代表unsigned short类型
//L 代表unsigned long类型
//Q 代表unsigned long long类型
//f 代表float类型
//d 代表double类型
//B 代表C++中的bool或者C99中的_Bool
//v 代表void类型
//* 代表char *类型
//@ 代表对象类型
//# 代表类对象 (Class)
//: 代表方法selector (SEL)
//[array type] 代表array
//{name=type…} 代表结构体
//(name=type…) 代表union
//bnum A bit field of num bits
//^type A pointer to type
//? An unknown type (among other things, this code is used for function pointers)
Class PersonClass = objc_allocateClassPair(NSObject.class, "Person", 0);
// 添加属性必须在objc_allocateClassPair和objc_registerClassPair之间
BOOL result = class_addIvar(PersonClass,
"_gender",
sizeof(NSString *),
log2(sizeof(NSString *)),
"@");
BOOL result2 = class_addIvar(PersonClass,
"_name",
sizeof(NSString *),
log2(sizeof(NSString *)),
"@");
// 也可以将 "@" 用@encode(NSString)表示
if (result && result2) {
objc_registerClassPair(PersonClass);
}
else {
objc_disposeClassPair(PersonClass);
}
// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html
// 结合文档, 添加属性需以T开头, V结尾
objc_property_attribute_t type = {"T", "@\"NSString\""};
objc_property_attribute_t ownership = {"C", ""};
objc_property_attribute_t nonatomic = {"N", ""};
objc_property_attribute_t backingIvar = {"V", "_name"};
objc_property_attribute_t attrs[] = {type, ownership, nonatomic, backingIvar};
class_addProperty(PersonClass, "name", attrs, 4);
SEL getter = NSSelectorFromString(@"name");
SEL setter = NSSelectorFromString(@"setName:");
// 添加方法
class_addMethod(PersonClass, getter, (IMP)personNameGetter, "@@:"); // or use method_getTypeEncoding for last argument
class_addMethod(PersonClass, setter, (IMP)personNameSetter, "v@:@");
// 以下为测试该类
Ivar ivar = class_getInstanceVariable(PersonClass, "_gender");
NSLog(@"Person ivar:%@",[NSString stringWithUTF8String:ivar_getName(ivar)]);
// 结果: Person ivar:_gender
objc_property_t prop = class_getProperty(PersonClass, "name");
NSLog(@"Person property:%@",[NSString stringWithUTF8String:property_getName(prop)]);
// 结果: Person property:name
Method method = class_getInstanceMethod(PersonClass, NSSelectorFromString(@"setName:"));
NSLog(@"%@", NSStringFromSelector(method_getName(method)));
// 结果: setName:
id person = [PersonClass new];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[person performSelector:setter withObject:@"Phoenix"];
NSLog(@"person name get:%@", [person performSelector:getter withObject:nil]);
#pragma clang diagnostic pop
// 结果: person name get:Phoenix