Runtime 属性

整体结构
objc_class
    |_ Class isa
        |_ NSObject

objc_class 的结构

Class super_class                                        OBJC2_UNAVAILABLE;
const char *name                                         OBJC2_UNAVAILABLE;
long version                                             OBJC2_UNAVAILABLE;
long info                                                OBJC2_UNAVAILABLE;
long instance_size                                       OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;

super_class 父类
name 类名称
ivars 属性列表
methodLists 方法列表
protocols 协议列表

基础概念:

IMP 指向定义方法起始的指针

id (*IMP)(id, SEL, ...)

第一个参数指向的是self,第二个参数指向方法选择器,后面是其他方法的参数

SEL 方法选择器
选择器由编译器生成,在类加载之后通过runtime自动生成

Method 类中定义的方法
Ivar 成员变量

property = Ivar + setter + getter

各种方法:

1.获取成员变量

Ivar sonProperty = class_getInstanceVariable(sonClass, "teacher");
NSString *teaher = object_getIvar(son, sonProperty);

2.获取成员变量列表

id sonClass = objc_getClass("Son");
unsigned int outCount;
Ivar *sonProperties = class_copyIvarList(sonClass, &outCount);
for (int i = 0; i < outCount; i++) {
    Ivar tempProperty = sonProperties[i];
    NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(tempProperty)];
    NSString *ivarContent = object_getIvar(son, tempProperty);
    NSLog(@"propertyName -> %@ property content -> %@", ivarName, ivarContent);
}
free(sonProperties);

3.获取属性列表

id sonClass = objc_getClass("Son");
unsigned int outCount;
objc_property_t *propertyList = class_copyPropertyList(sonClass, &outCount);
for (int i = 0; i < outCount; i++) {
    objc_property_t property = propertyList[i];
    NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
    NSString *propertyAttributes = [NSString stringWithUTF8String:property_getAttributes(property)];
    NSLog(@"propertyName -> %@ propertyAttributes -> %@", propertyName, propertyAttributes);
}
free(propertyList);

//    console output:
//    propertyName -> bikeName propertyAttributes -> T@"NSString",C,N,V_bikeName

属性类型字符串

编码 与property相对应的
R readonly
C copy
& retain
N nonatomic
GsampleName getter=sampleName
SsampleName setter=sanpleName
D dynamic
W __weak

4.添加property方法
此方法仅能够添加property,但还缺少对应的ivar,getter,setter。attributes中添加的是属性类型字符串。

id carClass = objc_getClass("Car");
@autoreleasepool {
    objc_property_attribute_t type = { "T", [[NSString stringWithFormat:@"@\"%@\"",NSStringFromClass([NSString class])] UTF8String] }; //type
    objc_property_attribute_t ownership0 = { "C", "" }; // C = copy
    objc_property_attribute_t ownership = { "N", "" }; //N = nonatomic
    objc_property_attribute_t backingivar  = { "V", [[NSString stringWithFormat:@"_%@", @"speed"] UTF8String] };  //variable name
    objc_property_attribute_t attrs[] = { type, ownership0, ownership, backingivar };
    
    BOOL isSuccess = class_addProperty(carClass, "speed", attrs, 4);
    NSLog(@"is success -> %d",isSuccess);
    //    console output:
    //    is success -> 1
}

5.添加成员变量方法
class_addIvar方法不能向已有的类添加成员变量,并且类不能是metaclass。

Class cls = objc_allocateClassPair(Car.class, "CarSubClass", 0);    //创建Car类的子类
BOOL isAddSuccess = class_addIvar(cls, "speed", sizeof(NSString *), log2(_Alignof(NSString *)), @encode(NSString));     //添加成员变量
objc_registerClassPair(cls);

if (isAddSuccess) {
    id accord = [[cls alloc] init];
    Ivar speed = class_getInstanceVariable(cls, "speed");
    object_setIvar(accord, speed, @"120");
    NSString *accordSpeed = object_getIvar(accord, speed);
    NSLog(@"accord speed -> %@",accordSpeed);
    //    console output:
    //    accord speed -> 120
}

参考代码 github链接

你可能感兴趣的:(Runtime 属性)