快速上手Runtime之方法交换

Posted iOS_Doman

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速上手Runtime之方法交换相关的知识,希望对你有一定的参考价值。

开发过程中,我们经常会用到系统类,而它提供的方法又不能完全满足我们开发的需要,那么在此时,我们需要为系统自带的方法扩展一些功能,而且还要保证原有的功能可正常使用.假设咱们现在有这么一个需求,我们在调用系统的[UIImage imageNamed:@"runtime"];的时候,我们并不能判断有没有加载成功,所以我们想在加载图片的时候并判断是否加载成功。

方案1:

 我们通常想到的就是分类,用分类添加一个方法,实现,然后在想要调用的地方导入头文件,去调用.

#import <UIKit/UIKit.h>

@interface UIImage (Method)

+(UIImage *)cdm_imageNamed:(NSString *)imageName;

@end


+(UIImage *)cdm_imageNamed:(NSString *)imageName
{
    //首先加载图片
    UIImage *image=[UIImage imageNamed:imageName];
    
    //然后实现功能【判断是否为空】
    
    if (image==nil) {
        NSLog(@"图片为空");
    }
    return image;
}

调用:

import "ViewController.h"
#import "UIImage+Method.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //分类实现:
    UIImage *image = [UIImage cdm_imageNamed:@"cdm"];
    
    
}

方案2:

利用runtime交换方法,我们调用系统的方法 实际是调用我们的方法:

步骤1.在分类加载的时候+(void)load;交换方法的实现 

步骤2.方法交换之前首先获取方法,因为交换方法的两个参数就是方法

步骤3.方法交换

+(void)load
{
    // 交换方法实现,方法都是定义在类里面
    // class_getInstanceMethod:获取对象
    // class_getClassMethod:获取类方法
    // IMP:方法实现
    
    // imageNamed
    // Class:获取哪个类方法
    // SEL:获取方法编号,根据SEL就能去对应的类找方法
    
    Method imageMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));
    
    Method cmd_imageMethod = class_getClassMethod([UIImage class], @selector(cdm_imageNamed:));
    
    //方法交换
    method_exchangeImplementations(imageMethod, cdm_imageMethod);
}

如果此时你认为完事了,调用系统的imageNamed方法,会造成死循环。因为我们在自定义的方法中加载图片调用的就是系统的imageNamed的方法,此时应该修改代码如下:

//运行时

+(UIImage *)cdm_imageNamed:(NSString *)imageName
{
    //修改为我们自己的方法,防止死循环
    UIImage *image=[UIImage cdm_imageNamed:imageName];
    
    //然后实现功能【判断是否为空】
    if (image==nil) {
        NSLog(@"图片为空");
    }
    return image;
}

 

调用实现:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //分类实现:
//    UIImage *image = [UIImage cdm_imageNamed:@"cdm"];
    
    //运行时实现:
    //调用imageNamed:实际上是调用cdm_imageNamed:
    UIImage *image = [UIImage imageNamed:@"cdm"];
    
}

 

效果图:

Demo地址:https://github.com/domanc/Method_Exchange.git

 

以上是关于快速上手Runtime之方法交换的主要内容,如果未能解决你的问题,请参考以下文章

ios runtime之交换方法method_exchangeImplementations的使用

iOS Runtime之方法替换

runtime总结二之消息机制(包括消息转发,消息交换的黑魔法)

快速上手React:

runtime:黑魔法之让人毫无知觉的修改类方法

iOS 为何使用runtime多次方法交换后却能按照交换顺序依次执行代码逻辑?