iOS中的runtime应用

作者: Gavin_peng | 来源:发表于2015-11-10 19:23 被阅读12093次

1.什么是runtime?

runtime是一套底层的C语言API,包含很多强大实用的C语言数据类型和C语言函数,平时我们编写的OC代码,底层都是基于runtime实现的。

2.runtime有什么作用?

1.能动态产生一个类,一个成员变量,一个方法
2.能动态修改一个类,一个成员变量,一个方法
3.能动态删除一个类,一个成员变量,一个方法

3.常用的头文件

 #import <objc/runtime.h> 包含对类、成员变量、属性、方法的操作
 #import <objc/message.h> 包含消息机制

4.常用方法

class_copyIvarList()返回一个指向类的成员变量数组的指针
class_copyPropertyList()返回一个指向类的属性数组的指针

<strong>注意:根据Apple官方runtime.h文档所示,上面两个方法返回的指针,在使用完毕之后必须free()。</strong>

ivar_getName()获取成员变量名-->C类型的字符串
property_getName()获取属性名-->C类型的字符串
-------------------------------------
typedef struct objc_method *Method;
class_getInstanceMethod() 
class_getClassMethod()以上两个函数传入返回Method类型
---------------------------------------------------
method_exchangeImplementations()交换两个方法的实现

5.runtime在开发中的用途

1.动态的遍历一个类的所有成员变量,用于字典转模型,归档解档操作
代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
/** 利用runtime遍历一个类的全部成员变量
1.导入头文件<objc/runtime.h> /
unsigned int count = 0;
/
* Ivar:表示成员变量类型 */
Ivar *ivars = class_copyIvarList([BDPerson class], &count);//获得一个指向该类成员变量的指针
for (int i =0; i < count; i ++) {
//获得Ivar
Ivar ivar = ivars[i]; //根据ivar获得其成员变量的名称--->C语言的字符串
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
NSLog(@"%d----%@",i,key);
}
}
运行结果如下:

成员变量遍历输出结果.png
获取一个类的全部属性:
获取类的属性的代码实现.png
结果如下: 输出结果.png
应用场景:
  • 可以利用遍历类的属性,来快速的进行归档操作。

  • 将从网络上下载的json数据进行字典转模型。
    注意:归档解档需要遵守<NSCoding>协议,实现以下两个方法
    - (void)encodeWithCoder:(NSCoder *)encoder{
    //归档存储自定义对象
    unsigned int count = 0;
    //获得指向该类所有属性的指针
    objc_property_t *properties = class_copyPropertyList([BDPerson class], &count);
    for (int i =0; i < count; i ++) {
    //获得
    objc_property_t property = properties[i]; //根据objc_property_t获得其属性的名称--->C语言的字符串
    const char *name = property_getName(property);
    NSString *key = [NSString stringWithUTF8String:name];
    // 编码每个属性,利用kVC取出每个属性对应的数值
    [encoder encodeObject:[self valueForKeyPath:key] forKey:key];
    }}

    - (instancetype)initWithCoder:(NSCoder *)decoder{    
          //归档存储自定义对象    
            unsigned int count = 0;   
         //获得指向该类所有属性的指针   
           objc_property_t *properties = class_copyPropertyList([BDPerson class], &count);   
           for (int i =0; i < count; i ++) {       
           objc_property_t property = properties[i];        //根据objc_property_t获得其属性的名称--->C语言的字符串       
           const char *name = property_getName(property); 
             NSString *key = [NSString stringWithUTF8String:name];        //解码每个属性,利用kVC取出每个属性对应的数值      
           [self setValue:[decoder decodeObjectForKey:key] forKeyPath:key];  
    }   
     return self;
    }
    

二、交换方法
通过runtime的method_exchangeImplementations(Method m1, Method m2)方法,可以进行交换方法的实现;一般用自己写的方法(常用在自己写的框架中,添加某些防错措施)来替换系统的方法实现,常用的地方有:

  • 在数组中,越界访问程序会崩,可以用自己的方法添加判断防止程序出现崩溃数组或字典中不能添加nil,如果添加程序会崩,用自己的方法替换系统防止系统崩溃
  • ...
    代码实现如下:


    运行程序崩溃.png 添加一个分类实现方法交换.png

    再次运行刚才的程序:


    最终运行结果图.png

相关文章

网友评论

  • 正儿八经的雷雷:厉害了,大弟弟
  • 87e2aaf4e5b7:-(void)gp_addObject:(id)object{

    if (object != nil) {
    [self gp_addObject:object];
    }
    }


    这个方法这样写不是死循环了吗,没看懂
    72332a7da5e7:@天道酬勤_XJL 因为两个方法已经交换了
    xiaofengl:额,为什么呀?
    87e2aaf4e5b7:哦,明白了,哈哈
  • iOS俱哥:数组添加nil成员,这个学到了 :v:
  • 3ee677025aa5:博主你好,我想请教一个问题。关于method_exchangeImplementations(Method m1, Method m2)这个方法,看截图你当时写的时候应该是能够成功替换addobject:这个方法,但是我现在使用相同的代码却无法实现替换。这是怎么回事呢? :joy:
    木槿WEIXIAO:@3ee677025aa5 class_getClassMethod你试试这个方法
    3ee677025aa5:哦哦,我找到原因了我使用的是[self class]。但是我有一点不明白,我使用[self class]可以成功替换协议和类目里面的方法,就是类里面的方法不能替换。请教一下博主这是为什么呢? :blush:
    Gavin_peng:@3ee677025aa5 我这边是没问题的呀,我觉得应该是你的这个地方写错了,因该是__NSArrayM,而不是_NSArrayM,是两个下划线而不是一个的。 :joy:
  • PPAbner:归档解档的拿来用了!!!嘿嘿!
    Gavin_peng:@PP_Abner 能帮到你就好,:ghost:
  • lele8446:学习了 :+1:
    Gavin_peng:@lele8446 是的,刚查了一下runtime的头文件,的确需要手动释放,感谢指正。 :clap:
    lele8446:@Gavin_peng Ivar *ivars = class_copyIvarList([BDPerson class], &count);
    这里是需要手动释放的吧 free(ivars);
    Gavin_peng:@lele8446 共同进步:beers:
  • 42bdacafc519:赞一个 :smile:

本文标题:iOS中的runtime应用

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