文档章节

iOS中IMP指针的运用

hanbing94
 hanbing94
发布于 2017/05/07 20:22
字数 818
阅读 41
收藏 0

iOS中如果对Runtime有一定了解的话,一定听说过或者用过这个函数 
void method_exchangeImplementations(Method m1, Method m2),它通常就是所说的method swizzling,算是ObjC的”黑魔法”了,作用就是在程序运行期间动态的给两个方法互换实现;

比如: 
程序中有许多个ViewController,我想在对项目改动最小的情况下,在当每个Controller执行完ViewDidLoad以后就在控制台把自己的名字打印出来,方便去做调试或者了解项目结构

其实我们的目的就是重写ViewDidLoad的方法,并在他的方法最后加上几句Log,所以我们需要给UIViewController建立一个category,因为我们知道,如果在Catagory中重写一个方法,就会覆盖它的原有方法实现,但是,这样做以后就没有办法调用系统原有的方法,因为在一个方法里调用自己的方法会是一个死循环。所以我们的解决办法就是,另外写一个方法来和viewDidLoad“交换”,这样外部调用viewDidLoad就会调到新建的这个方法中,同样,我们调用新建的方法就会调用到系统的viewDidLoad中了

第一种方案:

#import "UIViewController+viewDidLoad.h"
#import <objc/runtime.h>

@implementation UIViewController (viewDidLoad)

+ (void)load
{
    //保证交换方法只执行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        //获取这个类的viewDidLoad方法,它的类型是一个objc_moethod结构体的指针
        Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));

        //获取自定义的方法
        Method viewDidLoaded = class_getInstanceMethod(self, @selector(viewDidUnload));

        //互换两个方法实现
        method_exchangeImplementations(viewDidLoad, viewDidLoaded);

    });
}

//新建一个方法与viewDidload交换
- (void)viewDidLoaded
{
    [self viewDidLoaded];

    NSLog(@"%@ did load",self);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

第二种方案:

IMP 它是一个指向方法实现的指针,每一个方法都一个对应的IMP指针。我们可以直接调用方法的IMP指针,来避免方法调用死循环的问题

//修改的方法有返回值就用IMP,无返回值就用VIMP
typedef id   (*_IMP)  (id,SEL,...);
typedef void (*_VIMP) (id,SEL,...);

#import "UIViewController+viewDidLoad.h"
#import <objc/runtime.h>

@implementation UIViewController (viewDidLoad)

+ (void)load
{
    //保证交换方法只执行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        //获取原始方法
        Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));

        //获取方法实现
        _VIMP viewDidLoad_IMP = (_VIMP)method_getImplementation(viewDidLoad);

        //重新设置方法实现
        method_setImplementation(viewDidLoad,imp_implementationWithBlock(^(id target,SEL action){
            viewDidLoad_IMP(target,@selector(viewDidLoad));

            //自定义代码
            NSLog(@"%@ did load",target);
        }));
    });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

需要注意事项

修改的方法有返回值就用IMP,没有返回值就用VIMP。重写的方法有返回值,不要忘记在最后做return

实际上直接调用一个方法的IMP指针的效率是高于调用方法本身的,如果有一个合适的时机获取到方法的IMP的话,可以试着调用IMP而不用调用方法。

本文转载自:

共有 人打赏支持
hanbing94
粉丝 2
博文 67
码字总数 38602
作品 0
朝阳
私信 提问
如何实现一个IOS网络监控组件

此文由作者朱志强授权网易云社区发布。 Mobile Application Monitor IOS组件设计技术分享 背景 应用程序性能管理Application Performance Management(APM)是近年来比较火的互联网产业, Mo...

网易云
2018/12/11
0
0
[C++][IO]fstream用法

fstream用法 1. 打开文件 在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是: void open(const char* filename,int mode,int access); 参数: filename:  要打开的文件...

guitar_zp
2011/08/09
0
0
C++文件读写详解(ofstream,ifstream,fstream)

在看C++编程思想中,每个练习基本都是使用ofstream,ifstream,fstream,以前粗略知道其用法和含义,在看了几位大牛的博文后,进行整理和总结: 这里主要是讨论fstream的内容: [java] view pl...

涩女郎
2015/08/19
0
0
iOS 方法中 单指针和双指针的区别

iOS 双指针 iOS 单指针,双指针在方法参数中的区别 传入单指针,在方法内会复制一个临时的指针副本,在方法内操作的都是这个临时副本 传入双指针,在方法内会改变方法外 指针的指向 iOS 双指...

iOS_愛OS
2018/07/19
0
0
【AR】开始使用Vuforia开发iOS(2)

原 设置iOS开发环境 安装Vuforia iOS SDK 如何安装Vuforia iOS示例 编译并运行Vuforia iOS示例 支持iOS金属 iOS 64位迁移 设置iOS开发环境 适用于iOS的Vuforia引擎目前支持运行iOS 9及更高版...

lichong951
2018/06/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 白掌柜说了卖货不卖身

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @爱漫爱 :这是一场修行分享羽肿的单曲《Moony》 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :开不开心? 开心呀, 我又不爱睡懒觉…...

小小编辑
今天
8
0
大数据教程(11.7)hadoop2.9.1平台上仓库工具hive1.2.2搭建

上一篇文章介绍了hive2.3.4的搭建,然而这个版本已经不能稳定的支持mapreduce程序。本篇博主将分享hive1.2.2工具搭建全过程。先说明:本节就直接在上一节的hadoop环境中搭建了! 一、下载apa...

em_aaron
今天
3
0
开始看《JSP&Servlet学习笔记》

1:WEB应用简介。其中1.2.1对Web容器的工作流程写得不错 2:编写Servlet。搞清楚了Java的Web目录结构,以及Web.xml的一些配置作用。特别是讲了@WebServlet标签 3:请求与响应。更细致的讲了从...

max佩恩
今天
4
0
mysql分区功能详细介绍,以及实例

一,什么是数据库分区 前段时间写过一篇关于mysql分表的的文章,下面来说一下什么是数据库分区,以mysql为例。mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可...

吴伟祥
今天
3
0
SQL语句查询

1.1 排序 通过order by语句,可以将查询出的结果进行排序。放置在select语句的最后。 格式: SELECT * FROM 表名 ORDER BY 排序字段ASC|DESC; ASC 升序 (默认) DESC 降序 1.查询所有商品信息,...

stars永恒
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部