iOS-Runtime

RunTime简介
1.runtime是 OC 的底层实现, runtime API 都是纯 c 代码.
2.所有类中存在的东西,都可以用 runtime 来获得.
3.类:是给程序员看的, runtime: 转化成计算机能够看懂的东西.

Runtime基础介绍
1.获取属性

    //通过runtime获得类中属性的列表
    //就是返回的属性个数,也就是返回值的数组的count
    unsigned int outCount;
    objc_property_t * propertys = class_copyPropertyList(clazz, &outCount);
    for(int i = 0; i < outCount;i++)
    {
        //取出具体的某一个属性
        objc_property_t property = propertys[i];
        
        //获得类属性的名称
        const char * propertyName = property_getName(property);
        //转换成oc字符串
        NSString * propertyNameOC = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
        //NSLog(@"%@",propertyNameOC);
       
        //attributes 中获得重要信息
        //1.属性的数据类型是什么
        //2.属性与那个成员变量相关联
        const char * attributes = property_getAttributes(property);
        NSString * attributesString = [NSString stringWithCString:attributes encoding:NSUTF8StringEncoding];
        //NSLog(@"%@",attributesString);
    }

2.获取方法

    unsigned int outCount;
    //代表的就是方法
    Method * methods = class_copyMethodList(clazz, &outCount);
    for(int i = 0; i < outCount; i++)
    {
        Method method = methods[i];
        SEL methodSEL =  method_getName(method);
        NSLog(@"%@",NSStringFromSelector(methodSEL));
    }

3.获得类的所有成员变量

    unsigned int outCount;
    Ivar * vars = class_copyIvarList(clazz,&outCount);
    for(int i = 0; i < outCount;i++)
    {
        Ivar var = vars[i];
        NSString * varName = [NSString stringWithCString:ivar_getName(var) encoding:NSUTF8StringEncoding];
        NSLog(@"varName %@",varName);
    }

4.runtime调用方法

    ``` 
    //1.调用哪个对象的
    //2.什么方法
    //3.什么参数      
    objc_msgSend(<#id self#>, <#SEL op, ...#>)
    ```

    举例:
    ```
    NSDictionary * dict = @{@"name":@"白成慧",@"age":@(24)};
    Person * p = [[Person alloc] initWithDict:dict];

    objc_msgSend(p, @selector(setAge:),20);
    NSLog(@"%d",p.age);
    ```

Runtime 用法举例:
自己实现下KVC的两个重要的方法(虽然没什么意义,还是可以巩固下 runtime 的使用);
a. setValue: forKey方法的实现:

- (void)my_setValue:(id)value forKey:(NSString *)key
{
    //1.根据key值,把传递进来的value存储到对应的属性内部去
    
    //把传递进来的key转化成set方法,然后执行该set方法进行赋值
    //name
    //1.set
    //2.Namge:
    //setName:
    //把传递进来的key,首字母转换成大写,最终转换成符合set方法书写规则的字符串
    NSString * propertName = [key capitalizedString];//Name Age Number Tmp
    propertName = [NSString stringWithFormat:@"set%@:",propertName];
    
    //在把符合规则的set方法字符串转换成SEL类型
    SEL setSEL = NSSelectorFromString(propertName);

    //判断一下,如果是包装类,就行特殊的处理
    if([value isKindOfClass:[NSNumber class]])
    {
        objc_msgSend(self, setSEL,[value intValue]);
        return;
    }
    
    //setName:
    objc_msgSend(self, setSEL,value);
    
}

b.setValuesForKeysWithDictionary:方法的实现:

- (void)my_setValuesForKeysWithDictionary:(NSDictionary *)keyedValues
{
    
    for (int i = 0; i < keyedValues.allKeys.count;i++) {
        
        NSString * key = keyedValues.allKeys[i];
        id value = keyedValues.allValues[i];
        
        [self my_setValue:value forKey:key];
    }
}

你可能感兴趣的:(iOS-Runtime)