runtime解析及常用方法

什么是runtime?

  • runtime直译:运行时机制;OC发送消息的本质,就是 runtime去调用苹果底层的一些函数;

  • C语言在编译时,就知道该调用那些方法, 能成功调用吗;

  • 基于runtime的OC语言, 在编译阶段只要方法有声明,就不会报错;在运行时才会检测到底有没有方法,该调用哪个方法;

查看runtime底层实现:

  • 在终端编译文件 clang -rewrite-objc main.m Person.m 查看最终生成代码
    // 测试代码
    Person *p = [Person alloc];
    p = [p init];

生成cpp文件,找到对应代码:


    Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc"));

    p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("init"));

解析: 简化代码后,其实runtime底层也就是调用苹果封装的方法而已

   (Person *(*)(id, SEL))(void *) 强制类型转换, 把objc_msgSend转换成有返回值(Person *), 两个参数(id, SEL)的指向函数的指针;故可去掉,简化代码如下:

    Person *p = objc_msgSend([Person class], @selector(alloc));
    p = objc_msgSend(p, @selector(init));

由于苹果不推荐我们使用其底层的runtime, 但是有时一些功能只能由runtime实现,故我们首先配置Xcode(以XCocde7为例)
  • 导入头文件#import <objc/message.h>
  • 配置文件 : 项目 ---> BuildSetting ----> msg
Snip20160327_1.png

runtime常用方法:

  • 动态添加方法
    • 开发使用场景:如果一个类方法非常多,加载类到内存的时候要给每个方法生成相应映射表,非常耗费内存资源;这时候可以实现用动态给某个类添加方法.
    • 比如某应用的VIP用户才能使用一些功能.

代码实现:

@implementation Person

// 定义函数
// 默认OC方法都有两个隐式参数,self,_cmd
void run(id self, SEL _cmd) {
    NSLog(@"run");
}

// 只要调用没有实现的方法 就会来到方法
// 作用:去解决没有实现方法,动态添加方法
+ (BOOL)resolveInstanceMethod:(SEL)sel{

    if (sel == @selector(run)) {
        // 添加方法
        class_addMethod(self, sel, (IMP)run, nil);

        return YES;
    }

    return [super resolveInstanceMethod:sel];
}

@end

方法解析:
    // 添加方法到类
    class_addMethod(__unsafe_unretained Class cls, SEL name, IMP imp, const char *types);

        class:给谁添加方法
        SEL:添加哪个方法
        IMP:方法实现,函数入口,传入函数名
        type:方法类型 默认nil即可

然后我们利用performSelector方法调用一个没有实现的方法:

    [p performSelector:@selector(run)]

    // 会自动执行上面方法添加一个动态方法run
    // 打印输出:run

tips:

// 没有实现对象方法时,调用该方法
+(BOOL)resolveInstanceMethod:(SEL)sel {

    // 添加方法
}

// 没有实现类方法时, 调用该方法
+(BOOL)resolveClassMethod:(SEL)sel {

    // 添加方法
}
  • 交换两个方法的实现
  • 需求:想要在调用imageNamed加载图片时,提示是否加载成功,
  • 特别是大项目时,不希望更改系统方法(得改好多代码, 工作量忒大...)

此时可以使用runtime的动态交换方法来实现功能:

  • 新建一个UIImage的分类

  • 在分类中添加一个该功能的方法;(注意别覆盖系统方法)

  • 在+load方法中实现方法的交换

#import "UIImage+image.h"
#import <objc/message.h>

@implementation UIImage (image)
+(void)load {

    // 1.0 获取方法
    Method abel_imageNamed = class_getClassMethod(self, @selector(abel_imageNamed:));
    Method imageNamed = class_getClassMethod(self, @selector(imageNamed:));

    // 2.0 交换方法的实现
    method_exchangeImplementations(abel_imageNamed, imageNamed);

}

// 添加该功能方法
+ (UIImage *)abel_imageNamed:(NSString *)name
{
    // 调用系统方法
    UIImage *image = [self abel_imageNamed:name];

    // 添加功能
    if (image == nil) {

        NSLog(@"加载失败");
    }
    return image;
}

@end

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,281评论 25 707
  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 3,695评论 7 64
  • 1.今天早上六点二十才起床,洗漱完毕,开始做早餐,七点喊小儿起床,被他怒吼一声禁言,等他出来时已经是七点一刻了,胆...
    彩霞满天q2阅读 178评论 0 0
  • 1 如果你走在大街上,看着一个中年女人,一手插着兜,一手拿着烟,昂着头走路,那一定是我的母亲。 母亲从小命运多舛,...
    可可熊Q阅读 345评论 0 3
  • 早晨:遇见一个刚打完点滴手上胶布还没揭就在车上看书的小弟弟,觉得找到了学习不好的原因。 下午:遇见一个可爱的老奶奶...
    四娘jamie阅读 258评论 0 1