将来跳槽用

Runtime 10种用法

2018-05-25  本文已影响49人  二斤寂寞

转载runtime文章收集

runtime简介:

Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的。

人在江湖飘,身不由己啊。循环不停的业务,都几乎没有时间去总结。就是会用一些,但是真正想下runtime这个。自己还真说不出个所以然来。

爬爬帖子,给自己留个印儿。

OC最实用的runtime总结,面试、工作你看我就足够了!
让你快速上手Runtime
runtime详解
详解runtime运行时机制
万能控制器跳转

看一张图:


image.png

十大用法:

产品来一变态需求,推送过来的消息,要跳转到任意控制器.利用runtime动态生成对象、属性、方法这特性,我们可以先跟服务端商量好,定义跳转规则,比如要跳转到A控制器,需要传属性id、type,那么服务端返回字典给我,里面有控制器名,两个属性名跟属性值,客户端就可以根据控制器名生成对象,再用kvc给对象赋值,这样就搞定了。

组件化其实也用到了runtime,根据url,动态获取到类,参数等。可以参考蘑菇街开源项目

总结:

综上所述,runtime核心用法有一下三点。

Method class_getClassMethod(Class cls , SEL name) //获得某个类的类方法
Method class_getInstanceMethod(Class cls , SEL name) // 获得某个类的实例对象方法
void method_exchangeImplementations(Method m1 , Method m2) // 交换两个方法的实现
1、方法简单的交换

下面通过runtime 实现方法交换,类方法用class_getClassMethod ,对象方法用class_getInstanceMethod

// 获取两个类的类方法
Method m1 = class_getClassMethod([Person class], @selector(run));
Method m2 = class_getClassMethod([Person class], @selector(study));
// 开始交换方法实现
method_exchangeImplementations(m1, m2);
// 交换后,先打印学习,再打印跑!
[Person run];
[Person study];
2、拦截系统方法

步骤:
1、为UIImage建一个分类(UIImage+Category)
2、在分类中实现一个自定义方法,方法中写要在系统方法中加入的语句,比如版本判断

+ (UIImage *)xh_imageNamed:(NSString *)name {
    double version = [[UIDevice currentDevice].systemVersion doubleValue];
    if (version >= 7.0) {
        // 如果系统版本是7.0以上,使用另外一套文件名结尾是‘_os7’的扁平化图片
        name = [name stringByAppendingString:@"_os7"];
    }
    return [UIImage xh_imageNamed:name];
}

3、分类中重写UIImage的load方法,实现方法的交换(只要能让其执行一次方法交换语句,load再合适不过了)

+ (void)load {
    // 获取两个类的类方法
    Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
    Method m2 = class_getClassMethod([UIImage class], @selector(xh_imageNamed:));
    // 开始交换方法实现
    method_exchangeImplementations(m1, m2);
}

注意:自定义方法中最后一定要再调用一下系统的方法,让其有加载图片的功能,但是由于方法交换,系统的方法名已经变成了我们自定义的方法名(有点绕,就是用我们的名字能调用系统的方法,用系统的名字能调用我们的方法),这就实现了系统方法的拦截!

3、获得一个类的所有成员变量
Ivar *class_copyIvarList(Class cls , unsigned int *outCount) //获得一个类的所有成员变量
const char *ivar_getName(Ivar v) //获得成员变量的名字 
const char *ivar_getTypeEndcoding(Ivar v) //获得成员变量的类型
//获取Person类中所有成员变量的名字和类型
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([Person class], &outCount);

// 遍历所有成员变量
for (int i = 0; i < outCount; i++) {
    // 取出i位置对应的成员变量
    Ivar ivar = ivars[i];
    const char *name = ivar_getName(ivar);
    const char *type = ivar_getTypeEncoding(ivar);
    NSLog(@"成员变量名:%s 成员变量类型:%s",name,type);
}
// 注意释放内存!
free(ivars);
上一篇下一篇

猜你喜欢

热点阅读