美文网首页runtimeiOSiOS开发常用知识点
runtime简单使用之方法的交换

runtime简单使用之方法的交换

作者: Alexander | 来源:发表于2016-03-08 20:29 被阅读2232次

    一, 使用runtime实现方法的交换

    一, 前言

    • 在开发过程中,我们常常会遇到一种问题: 即当我们使用系统自带的方法时,发现系统方法的功能不能满足我们的需求,这时候需要我们给系统的方法添加额外的功能.

    • 下面以一个例子来实现给系统自带的方法添加额外的功能.

    • 项目背景 : 公司有个开发了很久的项目,之前使用添加图片的方法用的是:imageName:方法, 现在的项目需求是给系统自带的imageName:添加一个功能:如果下载的图片不存在,那么就提示我们当前下载的图片为空.

    • 思路 : 给系统自带的方法添加功能的几种方法

      • 1, 自定义类, 重写系统自带的imageName:方法,这种方法虽然可以实现,但是它的弊端就是必须要使用自己的类,依赖性强.
      • 2, 个UIImage添加一个分类, 改变系统类的实现,给系统的类添加方法的时候调用(强烈不推荐)
      • 3, 使用runtime的交互方法,给系统的方法添加功能. 具体实现 : 添加一个分类 --> 在分类中提供一个需要添加的功能的方法 --> 将这个方法的实现和系统自带的方法的实现交互.

    二, 步骤

    • 1, 新建一个继承自UIImage的分类,定义一个方法实现给系统的自带的方法添加功能.
    #import <UIKit/UIKit.h>
    
    @interface UIImage (WGImage)
    
    // 声明方法
    // 如果跟系统方法差不多功能,可以采取添加前缀,与系统方法区分
    + (UIImage *)wg_imageWithName:(NSString *)imageName;
    
    @end
    
    
    • 2, 实现方法的交互
    
     定义完毕新方法后,需要弄清楚什么时候实现与系统的方法交互?
     答 : 既然是给系统的方法添加额外的功能,换句话说,我们以后在开发中都是使用自己定义的方法,取代系统的方法,所以,当程序一启动,就要求能使用自己定义的功能方法.说道这里:我们必须要弄明白一下两个方法 :
     +(void)initialize(当类第一次被调用的时候就会调用该方法,整个程序运行中只会调用一次)
     + (void)load(当程序启动的时候就会调用该方法,换句话说,只要程序一启动就会调用load方法,整个程序运行中只会调用一次)
    
    
    + (void)load {
    /*
         self:UIImage
         谁的事情,谁开头 1.发送消息(对象:objc) 2.注册方法(方法编号:sel) 3.交互方法(方法:method) 4.获取方法(类:class)
         Method:方法名
    
         获取方法,方法保存到类
         Class:获取哪个类方法
         SEL:获取哪个方法
         imageName
    */
        // 获取imageName:方法的地址
        Method imageNameMethod = class_getClassMethod(self, @selector(imageNamed:));
    
        // 获取wg_imageWithName:方法的地址
        Method wg_imageWithNameMethod = class_getClassMethod(self, @selector(wg_imageWithName:));
    
        // 交换方法地址,相当于交换实现方式
        method_exchangeImplementations(imageNameMethod, wg_imageWithNameMethod);
    
    }
    
    
    • 3, 加载图片, 判断当前图片是否为空
    // 加载图片, 判断是否为空
    + (UIImage *)wg_imageWithName:(NSString *)imageName
    {
        // 这里调用imageWithName,相当于调用imageName
        UIImage *image = [UIImage wg_imageWithName:imageName];
        if (!image) {
            NSLog(@"Alex : 图片不存在");
        }
        return image;
    }
    
    
    • 4, 使用交互后的方法
    #import "ViewController.h"
    #import "WGStudent.h"
    #import "UIImage+WGImage.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
      //  wg_imageWithName ---> imageNamed(底层的操作 : 1, 下载图片. 2, 判断图片是否存在 )
        [UIImage imageNamed:@"WilliamAlex.png"];
    }
    
    @end
    
    • 5, 打印结果
    2016-03-08 17:29:50.372 fdsfsdf[1545:96854] Alex : 图片不存在
    
    

    知识拓展

    • 不能在分类中重写系统方法imageNamed,因为会把系统的功能给覆盖掉,而且分类中不能调用super.

    相关文章

      网友评论

      • 科24:为甚我的不执行 wg_imageWithName内部的判断
      • ca7508dad23b:刚入门时候runtime的理论知识让自己一头雾水,谢谢你简单明了的实际例子。真心感谢!

      本文标题:runtime简单使用之方法的交换

      本文链接:https://www.haomeiwen.com/subject/kspzkttx.html