zoukankan      html  css  js  c++  java
  • 快速上手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

  • 相关阅读:
    什么是架构
    jenkins权限插件配置
    解决Error response from daemon: oci runtime error: container_linux.go:247: starting container process
    解决“/tmp/crontab bad minute”问题
    yml链接mysql路径serverTimezone=UTC的那些坑
    java请求头导致特殊字符为空问题
    使用ssh连接WSL
    系统设计与任务分配
    需求规格说明书
    选题报告
  • 原文地址:https://www.cnblogs.com/dianming/p/6606128.html
Copyright © 2011-2022 走看看