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)

时间: 2024-11-06 09:14:16

Runtime 应用(一)拦截系统自带的方法交换实现的相关文章

C# 不用系统自带的方法将字符串类型123456转换为值类型

C# 不用系统自带的方法将字符串类型123456转换为值类型 static void Main(string[] args) { string numString = "123045"; long num = GetNum(numString); Console.WriteLine(num); } private static long[] ten = new long[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 };

快速上手Runtime(三)之方法交换

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

iOS开发——运行时OC篇&amp;使用运行时获取系统的属性:使用自己的手势修改系统自带的手势

使用运行时获取系统的属性:使用自己的手势修改系统自带的手势 有的时候我需要实现一个功能,但是没有想到很好的方法或者想到了方法只是那个方法实现起来太麻烦,一或者确实为了装逼,我们就会想到iOS开发中最牛逼的技术运行时(Runtime) 关于运行时这里就不多说了,请查看笔者之前搬过来了精选文章,这里主要是怎么在实际开发中使用运行时实现我们想要的功能. 比如,在iOS开发中有这样一个问题,关于导航栏中我们点击一个按钮会跳到对应的子控制器,但是这里问题就来了,我们在对应的字控制器中可以点击对应的back

HDU 1257(最小拦截系统)

Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不 能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统. Input 输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此

提取了Windows 10 Build 9901 系统自带 高清分辨率壁纸

提取了Windows 10 Build 9901  系统自带 高清分辨率壁纸 下载地址为:http://www.400gb.com/file/81555894

Mac系统自带的Python版本切换

由于需要安装各种python包,所以需要在Mac中端输入各种pip install xxxxxx的命令. 问题:直接运行pip install xxxxxx后,包会安装到系统自带的2.7版本的Python中,而在用高级版本的Python时会出现仍然缺失这个包的现象. 解决:不用删除系统自带的Python2.7的版本(有文章说删除以后系统中由该版本支持的部分会出错),只要在安装时输入pip3 install xxxxx就行了,同理使用python3代替python指令,这样一来,python代表系

最少拦截系统

先吐槽一句!九度关了!!!!!!!!我的账号密码竟然不对了.... Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统. Inp

HDU 1257 最少拦截系统

http://acm.hdu.edu.cn/showproblem.php? pid=1257 题目大意: 有一种导弹拦截系统,每次仅仅能发射比前一发导弹低的炮弹,给定一些导弹的突击顺序,求至少须要多少导弹拦截系统来全然阻止 思路: 好久没做题.做题水的~ 直接模拟就可以~ #include<cstdio> const int MAXN = 30000 + 10; const int INF = 0x3ffffff; int a[MAXN], ans; int cur_max[MAXN]; /

[2016-03-27][HDU][1257][最少拦截系统]

时间:2016-03-27 14:51:35 星期日 题目编号:[2016-03-27][HDU][1257][最少拦截系统] 分析:贪心,每当不能拦截就增加一个拦截系统,可以发现,每个拦截系统拦截的高度比较和出现的顺序一样.即第二个系统始终比第一个系统拦截的高度高 #include <cstdio> using namespace std; int a[30000 + 10]; int main(){ int n,b,flg; while(~scanf("%d",&