iOS-Swizzle
最后更新: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-warningvoid 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@
/////////////////////////////////////////////////////////////////////////////////////////////////// ... 什么是runtime? 1> runtime是一套底层的C语言API(包含很多强大实用的C语言数据类型.C语言函数)2> 实际上,平时我们编写的OC代码,底层都是基于runtime实现的* ... 1.是否可以把比较耗时的操作放在通知中心中? 通知在哪一个线程发的,那么对通知事件的处理就在同一个线程中进行; 如果在异步线程发的通知,那么可以执行比较耗时的操作: 如果在主线程发的通知,那么就不 ... ios runtime swizzle @implementation NSObject(Extension) + (void)swizzleClassMethod:(Class)class orig ... Method Swizzle黑魔法,修改 ios 系统类库方法 版权声明:本文为博主原创文章,未经博主允许不得转载. 一般来说,系统提供的方法已经足够开发了,但是有的时候有些需求用普通方法不好做. ... 开源 iOS 项目分类索引大全 GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助 系统基础库 Category/Util sstoolkit 一套Cate ... 概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ... 1:iOS视图控制对象生命周期 init-初始化程序 viewDidLoad-加载视图 viewWillAppear-UIViewController对象的视图即将加入窗口时调用: viewDidAp ... 概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ... Runtime是想要做好iOS开发,或者说是真正的深刻的掌握OC这门语言所必需理解的东西.最近在学习Runtime,有自己的一些心得,整理如下,一为 查阅方便二为 或许能给他人一些启发,三为 希望得到 ... mysql恢复数据时中文乱码,解决办法. 用source命令导入mysql数据库怎么设置中文编码 1.导出数据时指定编码在导出mysql sql执行文件的时候,指定一下编码格式: mysqldump ... vue $forceUpdate() 强制重新渲染:https://blog.csdn.net/z9061/article/details/94862047 MyBatis中,出现Unknown column的提示是mapper.xml中的数据库字段写错了. 错误示例: XxMapper.xml中 <sql id="KnowlegeSect ... 1. 使用UI线程的SynchronizationContext的Post/Send方法,这种情况一般在窗体构造函数或者FormLoad中获取同步上下文: 范例: public partial cla ... 假设每个人有个开发分支,想隔一段时间就把自己的开发分支上的代码保持和测试分支一直,则需要如下操作: 1.我想将test分支上的代码完全覆盖dev分支,首先切换到dev分支git checkout de ... package ba; import java.io.*; public class zifuTest { public static void main(String[] args) { FileI ... 1.CollectionView的刷新必须首先保证CollectionView有高度 注意事项:在cell中嵌套CollectionView,如果使用的是AutoLayout的话,一定要注意保证Col ... django的路由系统: 一.基本用法: 1.path('index', views.index), # 通过类的方式创建url映射 2.path('home', views.Home.as_view ... 升级win10后,发现一直可以用的MarkdownPad2预览功能不可以用了.于是在网上搜索了一下,刚开始没有解决.不过现在可以了.现在把解决方案记录下来.Windows10上使用MarkdownPa ... https://juejin.im/post/5d674ac2e51d4557ca7fdd70 Redis占用内存大小 我们知道Redis是基于内存的key-value数据库,因为系统的内存大小有限, ...iOS-Swizzle的更多相关文章
随机推荐