美文网首页
Runtime 属性

Runtime 属性

作者: docallsama | 来源:发表于2017-11-27 17:03 被阅读10次

    整体结构
    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 属性

          本文链接:https://www.haomeiwen.com/subject/wnsbmxtx.html