runtime笔记

2018-04-08  本文已影响0人  小刘_假装是个程序员

苹果不推荐我们使用runtime, 因此runtime是没有提示的。
打开提示将如下参数设置为no


image.png

我们通过2种调用类的实例方法的过程来研究
一下OC代码是如何转换成runtime代码的

@interface SWPerson : NSObject

- (void )eat;

@end

@implementation SWPerson
- (void )eat
{
    NSLog(@"吃饭");
    
}
@end

OC代码

    SWPerson *p = [[SWPerson alloc]init];
    [p eat];

image.png

runtime代码

    id p = objc_msgSend(objc_getClass("SWPerson"), sel_registerName("alloc"));
    objc_msgSend(p, sel_registerName("init"));
    objc_msgSend(p, sel_registerName("eat"));
image.png

OC代码实际上都会被编译器转换成 runtime代码执行。

runtime应用一 修改系统方法的实现

下面的方法将 imageNamed: 改成 imageWithNamed:执行。
这样可以做到监听系统的方法,然后在需要的时候 执行。
.h文件

#import <UIKit/UIKit.h>

@interface UIImage (exchange)

+ (UIImage *)imageWithNamed:(NSString *)name;

@end

.m文件

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

@implementation UIImage (exchange)

+(void)load{
    Method systemMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));
    Method custormMethod = class_getClassMethod([UIImage class], @selector(imageWithNamed:));
    method_exchangeImplementations(systemMethod, custormMethod);
}

+ (UIImage *)imageWithNamed:(NSString *)name{
    
    UIImage *image = [UIImage imageWithNamed:name];
    if (image == nil) {
        NSLog(@"%@图片加载失败",name);
    }
    return image;
}

@end

原理解析
1 image对象找到该方法对应的编号;
2 通过方法的编号,找到方法列表中对应的方法
3 通过找到了方法列表中对应的方法,找到对应的方法的实现
4 在以上三点方法开始之前,我们通过load方法在OC的底层实现了对两个方法实现的交换
5 当外面用对象调用(imageNamed:)的方法的时候其实由于交换的方法实现的原因,该对象会去找(imageWithNamed:)方法的实现,当程序进入了(imageWithNamed:)方法的时候,在运行第二个(imageWithNamed:)方法的时候,其实是调用(imageNamed:)方法,然后再进行判断,如果输入的不是图片,那么自然的显示,加载失败.这就是runtime的交换方法.

上一篇下一篇

猜你喜欢

热点阅读