zoukankan      html  css  js  c++  java
  • Runtime 应用(一)拦截系统自带的方法交换实现

    动态的交换方法能够给项目中大量已经使用的方法 进行拦截增加操作

    实践:利用运行时交换系统的ImageNamed:方法

    应用背景

    当系统需要适配ios7和ios8时可能会有显示不同图片的需求,但在老项目上开发ios7程序时并未考虑到ios8的适配,当项目上有几百处地方用到ImageNamed:方法时,如果选用最直接的办法,在该方法之前进行判断,如果为ios8就显示另外一张图片,这样的工作量明显会很大,所以可以用运行时的方法来解决。

    新建一个项目,准备两张图片,一张图片名为close为ios7而准备,一张close_os8为ios8而准备

    在storyboard里添加两个个UIImageView控件

    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *img1;
    @property (weak, nonatomic) IBOutlet UIImageView *img2;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.img1.image = [UIImage imageNamed:@"close"];
        self.img2.image = [UIImage imageNamed:@"fire"];
        
    }
    
    @end

    接下来使用运行时的方法交换imageNamed:的实现,先为UiImage添加一个自定义的创建图片的分类,此时需要导入一个运行时框架 #import<objc/runtime.h>,

    代码如下:

    /**
     *  自定义创建图片方法
     */
    + (instancetype)imageWithName:(NSString *)name
    {
        NSString *imgN = name;
        double version = [[UIDevice currentDevice].systemVersion doubleValue];
        NSLog(@"%f",version);
        if (version >= 8.0) {
            imgN = [NSString stringWithFormat:@"%@_os8",name];
            NSLog(@"%@",imgN);
        }
        // 此时imageWithName:的实现在运行时已经被改为imageNamed:的实现
        return [self imageWithName:imgN];
    }

    在load方法里面实现方法的交换,该方法只会被加载一次

    /**
     *  类第一次加载进内存的时候会调用
     */
    + (void)load
    {
        // 运行时交换两个方法的实现
        Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
        Method m2 = class_getClassMethod([UIImage class], @selector(imageWithName:));
        method_exchangeImplementations(m1, m2);
        
    }

     如此就利用运行时机制实现了系统方法和自定义方法互相交换实现

    需要了解的知识点

    一、什么是运行时

         运行时是一套纯C语言的API,编译器最终都会将OC代码转化为运行时代码。

    二、运行时常用函数

    1、<objc/runtime.h>

    * 获得某个类的类方法 Method class_getClassMethod(Class cls, SEL name)

    * 获得某个对象的对象方法 Method class_getInstanceMethod(Class cls, SEL name)

    * 交换两个方法的实现 void method_exchangeImplementations(Method m1, Method m2)

    * 关联对象(将值value与对象object关联起来) void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

    参数key:将来可以通过key取出这个存储的值

    参数policy:存储策略(assign、copy、retain)

    * 利用参数key将对象中存储的对应值取出 id objc_getAssociatedObject(id object, const void *key)

    * 获得某个类的所有成员变量 Ivar *class_copyIvarList(Class cls, unsigned int *outCount)(outCount会返回成员变量的总数)

    * 获得成员变量的名字 const char *ivar_getName(Ivar v)

    * 获得成员变量的类型 const char *ivar_getTypeEncoding(Ivar v)

    * 释放内存 void      free(void *) (当C语言函数名中包含了copy、create、retain、new等词语,那么就需要在最后释放资源)

    2、<objc/message.h>

    * 给某个对象发送某个消息 void objc_msgSend(void)

  • 相关阅读:
    POJ 1469 COURSES 二分图最大匹配
    POJ 1325 Machine Schedule 二分图最大匹配
    USACO Humble Numbers DP?
    SGU 194 Reactor Cooling 带容量上下限制的网络流
    POJ 3084 Panic Room 求最小割
    ZOJ 2587 Unique Attack 判断最小割是否唯一
    Poj 1815 Friendship 枚举+求最小割
    POJ 3308 Paratroopers 最小点权覆盖 求最小割
    1227. Rally Championship
    Etaoin Shrdlu
  • 原文地址:https://www.cnblogs.com/junhuawang/p/5798757.html
Copyright © 2011-2022 走看看