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,有自己的一些心得,整理如下,一为 查阅方便二为 或许能给他人一些启发,三为 希望得到 ... 4.7.开发Web应用程序 Spring Boot非常适合于Web应用程序开发.您可以使用嵌入式Tomcat,Jetty,Undertow或Netty创建独立的HTTP服务器.大多数Web应用程序都使 ... 4.10.使用SQL数据库 从使用JdbcTemplate直接的JDBC访问到完整的"对象关系映射"技术(例如Hibernate),Spring框架为使用SQL数据库提供了广泛的支 ... 一.1. upper()作用:将字符串中字符转换为大写 In [17]: spam Out[17]: 'hello,world' In [18]: print(spam.upper()) HELLO, ... 记事本的打开与保存 一些总结 * Swing中有时方法不显示,需要把方setVisible(true)放到最后执行 * AWT中的TextArea默认是中间布局 * fileDialog对话框Load ... char* p = malloc(1024);char* q = realloc(p,2048); 现在的问题是我们应该如何处理指针 p. 刚开始按照我最直观的理解,如果就是直接将 p = NULL; ... ##1-JMeter4export JMETER_HOME=/Users/wulei/softwares/installedsoftwares/apache-jmeter-4.0export CLAS ... 一.C/S与B/S的区别 C/S(Client/Server):客户端/服务器 1)一般使用的软件都是C/S架构,比如QQ.360.office365: 2)C表示客户端,用户通过客户端来使用软件:S ... 1. 建立一个console工程 QT -= gui CONFIG += c++ console CONFIG -= app_bundle # The following define makes y ... 泛型的声明 与Java不同的是,Kotlin要求类型实参要么被显示的说明,要么能被编译器推导出来.因为Java在1.5版本才引入泛型,所以为了兼容过去的版本,可以不直接声明List类型的变量,而不说明 ... 521. "North-East" Time limit per test: 0.5 second(s)Memory limit: 262144 kilobytes input: ...iOS-Swizzle的更多相关文章
随机推荐