最后更新:2017-06-21

一、先说结论

void swizzleMethod(Class cls, SEL originalSelector, SEL swizzledSelector)
{
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector); BOOL didAddMethod =
class_addMethod(cls,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod)); if (didAddMethod) {
class_replaceMethod(cls,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}

二、代码分析

2.1 class_getInstanceMethod()

获取某个类实例的方法, 如果该类实例没有此方法, 则返回NULL

Method swizzleMethod = class_getInstanceMethod([Person class], @selector(run));
if (swizzleMethod == NULL) {
NSLog(@"NULL");
}

参数解释

class_getInstanceMethod(Class cls, SEL name)

cls: 获取方法的类

name: 方法的名称

2.2 class_addMethod()

参数解释

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

cls: 获取方法的类

name: 添加的方法方法的名称

imp: 方法的实现,也就一个指向方法的指针

const char *types: 定义了返回值类型和参数类型的字符串(下面会提到)

返回值

YES: 增加方法成功

NO: 增加方法失败,例如 (如果目标类(Person) 实现了该方法,那么会返回 NO)

注意点

  • class_addMethod 能够覆盖父类的实现的;

    如果目标类有实现了该方法,class_addMethod就会失败

class_addMethod will add an override of a superclass's implementation

  • 处理警告问题

    参考: https://stackoverflow.com/questions/6224976/how-to-get-rid-of-the-undeclared-selector-warning

    void sayHello(id self, SEL _cmd, NSString *word)
    {
    NSLog(@"%@", word);
    } - (void)viewDidLoad {
    [super viewDidLoad]; #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wundeclared-selector"
    class_addMethod([Person class], @selector(resolveThisMethodDynamically:), (IMP)sayHello, "v@:@");
    Person *p = [[Person alloc] init];
    [p performSelector:@selector(resolveThisMethodDynamically:) withObject:@"hello"];
    #pragma clang diagnostic pop }
  • 需要动态调用,因为通过运行时添加的方法,直接调用 编译不过的

    正确做法:
    [p performSelector:@selector(resolveThisMethodDynamically:) withObject:@"hello"]; 错误做法,编译不过
    [p resolveThisMethodDynamically:@"hello"];
  • imp 默认自带两个参数, id类型 以及 SEL 类型

    void sayHello(id self, SEL _cmd, ...)

2.3 参数 const char *types 解释

v 表示的是void 类型

i 表示整数类型

@ 表示一个对象

: 表示一个方法

v@: 表示的是返回值类型是void, 一个参数是对象(id self),另一个参数为方法 (SEL _cmd)

v@

iOS-Swizzle的更多相关文章

  1. IOS Swizzle(hook)

    /////////////////////////////////////////////////////////////////////////////////////////////////// ...

  2. IOS Runtime的用法

    什么是runtime? 1> runtime是一套底层的C语言API(包含很多强大实用的C语言数据类型.C语言函数)2> 实际上,平时我们编写的OC代码,底层都是基于runtime实现的* ...

  3. Objective-C:运行时runtime

    1.是否可以把比较耗时的操作放在通知中心中?   通知在哪一个线程发的,那么对通知事件的处理就在同一个线程中进行; 如果在异步线程发的通知,那么可以执行比较耗时的操作: 如果在主线程发的通知,那么就不 ...

  4. ios runtime swizzle

    ios runtime swizzle @implementation NSObject(Extension) + (void)swizzleClassMethod:(Class)class orig ...

  5. Method Swizzle黑魔法,修改 ios 系统类库方法 SEL IMP

    Method Swizzle黑魔法,修改 ios 系统类库方法   版权声明:本文为博主原创文章,未经博主允许不得转载. 一般来说,系统提供的方法已经足够开发了,但是有的时候有些需求用普通方法不好做. ...

  6. 开源 iOS 项目分类索引大全 - 待整理

    开源 iOS 项目分类索引大全 GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助 系统基础库 Category/Util sstoolkit 一套Cate ...

  7. iOS开发系列--Swift进阶

    概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...

  8. IOS开发基础知识--碎片35

    1:iOS视图控制对象生命周期 init-初始化程序 viewDidLoad-加载视图 viewWillAppear-UIViewController对象的视图即将加入窗口时调用: viewDidAp ...

  9. 【原】iOS动态性(三) Method Swizzling以及AOP编程:在运行时进行代码注入

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  10. iOS Run_time

    Runtime是想要做好iOS开发,或者说是真正的深刻的掌握OC这门语言所必需理解的东西.最近在学习Runtime,有自己的一些心得,整理如下,一为 查阅方便二为 或许能给他人一些启发,三为 希望得到 ...

随机推荐

  1. [19/09/19-星期四] Python中的字典和集合

    一.字典 # 字典 # 使用 {} 来创建字典 d = {} # 创建了一个空字典 # 创建一个保护有数据的字典 # 语法: # {key:value,key:value,key:value} # 字 ...

  2. kubernetes快速应用入门

    kubectl 就是 api server的客户端工具 创建一个nginx的pod [root@master ~]# kubectl run nginx-deploy --image=nginx:1. ...

  3. linux之网卡绑定

    1 什么是网卡绑定 将多块网卡绑定同一IP地址对外提供服务,可以实现高可用或者负载均衡.直接给两块网卡设置同一IP地址是不可以的.通过bonding,虚拟一块网卡对外提供连接,物理网卡的被修改为相同的 ...

  4. roslyn\csc.exe

    vs2019调试运行时提示roslyn\csc.exe错误时在nuget包管理器控制台里输入:  Update-Package Microsoft.CodeDom.Providers.DotNetCo ...

  5. 嘉馨学姐又双叒叕来吃包子了 QDUOJ 模拟 尺度法

    嘉馨学姐又双叒叕来吃包子了 QDUOJ 模拟 尺度法 点我进入OJ题目详情 题意 给你一串数,让你求长度最长的子串,这个字串满足里面没有重复出现的数字. 解题思路 使用一个标记数组,来标记每个数的第一 ...

  6. ES6 系列之异步处理实战

    前言 我们以查找指定目录下的最大文件为例,感受从 回调函数 -> Promise -> Generator -> Async 异步处理方式的改变. API 介绍 为了实现这个功能,我 ...

  7. Java——BufferedImage操作实例

    通过鼠标位置改变图像ColorModel对象索引,从而实现图像像素自动变化 BufferedImage 由图像数据的 ColorModel 和 Raster 组成.Raster 的 SampleMod ...

  8. XADC

    XADC实验 1.XADC概述 Xilinx7系列内部自带一个双通道12位分辨率的高速(1MSPS 1M sample per second)采样速率的模拟混合信号处理模块,双通道的ADC支持单极和差 ...

  9. Android真机测试时无法连接服务器

    之前服务器的通信一直是在模拟机上实现的,今天用在真机上却不成功.百度之后发现是安卓9以后禁止使用HTTP直接访问服务器.记录一下以后使用. 参考博文:https://blog.csdn.net/don ...

  10. datatable和dataset的区别

    DataSet 是离线的数据源 DataTable 是数据源中的表.当然也可以自己建一张虚表.插入数据库中 DataSet是DataTable的容器DataSet可以比作一个内存中的数据库,DataT ...