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)
Runtime 应用(一)拦截系统自带的方法交换实现的更多相关文章
- 快速上手Runtime(三)之方法交换
开发过程中,我们经常会用到系统类,而它提供的方法又不能完全满足我们开发的需要,那么在此时,我们需要为系统自带的方法扩展一些功能,而且还要保证原有的功能可正常使用.假设咱们现在有这么一个需求,我们在调用 ...
- iOS开发——运行时OC篇&使用运行时获取系统的属性:使用自己的手势修改系统自带的手势
使用运行时获取系统的属性:使用自己的手势修改系统自带的手势 有的时候我需要实现一个功能,但是没有想到很好的方法或者想到了方法只是那个方法实现起来太麻烦,一或者确实为了装逼,我们就会想到iOS开发中最牛 ...
- Notepad2替代系统自带的记事本
事情是这样的,平时我经常把一些文字复制到记事本中编辑好了再复制到目标位置,可以在系统自带的记事本中替换删除一些内容,记事本小巧,占用很少的资源,我很喜欢:但今天复制的内容中有很多数字和一些我不想要的内 ...
- 如何获取安卓系统自带应用的package和activity
之前在做appium自动化测试的时候,参考网上的例子,运行安卓系统自带的app,所以,就需要获取系统自带的package(包名)和activity.这里简单记录一下,不一定适合所有的系统应用. 运行环 ...
- 重装系统后如何删除系统自带的office2003
背景:操作系统重装后,系统自带的office2003版本太低不好使用,需要安装更高版本的如2010,但是卸载时提示“无法打开此修补程序包……”,从而无法卸载.经网上查询,采用以下解决办法: 在注册表中 ...
- C语言中使用系统自带的快排函数
题目 . 德才论 () 宋代史学家司马光在<资治通鉴>中有一段著名的"德才论":"是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取 ...
- HDU 1257 最少拦截系统【LIS】
题意:类似于套娃娃,问最少需要多少个拦截系统. 思路: 假设已经有m个导弹拦截序列 r1:x11>=x12>=x13>=...>=x1n r1:x21>=x22>= ...
- HDU-1257 导弹拦截系统 http://acm.hdu.edu.cn/showproblem.php?pid=1257
Problem Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高 ...
- Ios二维码扫描(系统自带的二维码扫描)
Ios二维码扫描 这里给大家介绍的时如何使用系统自带的二维码扫描方法和一些简单的动画! 操作步骤: 1).首先你需要搭建UI界面如图:下图我用了俩个imageview和一个label 2).你需要在你 ...
随机推荐
- anki插件推荐
记忆是一件需要反复重复的事情,可是怎么花最小的代价来重复呢? 著名的艾宾浩斯遗忘曲线是一个统计学的概念,非常具有参考价值,但是对于不同的人来说,是有差别的,另外操作起来也比较麻烦. 好在现在有许多记忆 ...
- CentOS 7 系统下安装gnome图形界面
在安装Gnome 包之前,我们需要先检查下安装源是否正常,因为我们要通过yum命令来安装gnome包, 而yum命令式通过yum 源来下载安装包的. 1.在命令行下输入下面的命令来安装 Gnome 包 ...
- PHP框架之ThinkPHP项目CMS内容管理系统源码及开发手册视频
http://download.csdn.net/download/duguqing/4203042
- 10 个强大的JavaScript / jQuery 模板引擎推荐
模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档.由于在开发过程中,网站或应用程序的界面与数据实现分离,大大提升了开发效率,良好的设计也使得代码重用变得更加容易. 本文 ...
- Hbase导入MapReduce数据的时候提示Running Job XXXX后就一直卡着不动
代码确信无误之后,ant运行起来,发现一执行就卡在Running Job XXXX那里一直不动了. 试着把代码打包成jar扔到Linux执行也还是一样的效果.还是停在那里.然后就一顿瞎蒙.最后发现是H ...
- 【转】【Mysql】MySQL添加用户、删除用户与授权
MySql中添加用户,新建数据库,用户授权,删除用户,修改密码(注意每行后边都跟个;表示一个命令语句结束): 1.新建用户 1.1 登录MYSQL: @>mysql -u root -p @&g ...
- motion的移植和使用
说明: motion主页:http://www.lavrsen.dk/foswiki/bin/view/Motion motion下载地址:http://sourceforge.net/project ...
- (转)windows平台时间函数性能比较QueryPerformanceCounter,GetTickCount,ftime,time,GetLocalTime,GetSystemTimeAsFileTime
执行 10000000 次, 耗时 2258,369 微秒 QueryPerformanceCounter 执行 10000000 次, 耗时 26,347 微秒 GetTickCoun ...
- linux -- ubuntu dash bash
终端:即所谓的命令行界面,又称命令终端,用户输入shell命令用的窗口,跟Windows里的DOS界面差不多. shell:意为“壳”,是操作系统与用户交互用的接口,在命令终端里可以使用shell.s ...
- 关于lockkeyword
线程同步对象keywordlock,是以lock相应的object对象为准,即随意线程lock住lockObj对象之后,其它线程不管在其它不论什么代码段使用lock(lockObj)去进行线程同步时, ...