接上一篇 http://www.cnblogs.com/ddavidXu/p/5924597.html
转载来源http://www.jianshu.com/p/6b905584f536
http://southpeak.github.io/2014/10/30/objective-c-runtime-2/
runtime的黑魔法,就是可以实现交换两个方法的实现,这就意味着我们可以修改系统的方法实现。
栗子:当UIViewController及其子类的对象调用viewWillAppear时,都会打印一条日志信息。
#import <objc/runtime.h> @implementation UIViewController (Tracking) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Class class = [self class]; // When swizzling a class method, use the following: // Class class = object_getClass((id)self); SEL originalSelector = @selector(viewWillAppear:); SEL swizzledSelector = @selector(xxx_viewWillAppear:); Method originalMethod = class_getInstanceMethod(class, originalSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (didAddMethod) { class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } }); } #pragma mark - Method Swizzling - (void)xxx_viewWillAppear:(BOOL)animated { [self xxx_viewWillAppear:animated]; NSLog(@"viewWillAppear: %@", self); } @end
因为关于method swizzling方法的介绍非常多,就不详细说了,
大致原理图
需要注意一下几点
-
Swizzling应该总是在+load中执行
-
Swizzling应该总是在dispatch_once中执行
原因,method swizzling会影响到类的全局状态,避免在并发处理中出现竞争的情况,不管有多少个线程,确保代码只被执行一次。
选择器(selector)、方法(method)和实现(implementation)
- Selector(typedef struct objc_selector *SEL):用于在运行时中表示一个方法的名称。一个方法选择器是一个C字符串,它是在Objective-C运行时被注册的。选择器由编译器生成,并且在类被加载时由运行时自动做映射操作。
- Method(typedef struct objc_method *Method):在类定义中表示方法的类型
- Implementation(typedef id (*IMP)(id, SEL, …)):这是一个指针类型,指向方法实现函数的开始位置。这个函数使用为当前CPU架构实现的标准C调用规范。每一个参数是指向对象自身的指针(self),第二个参数是方法选择器。然后是方法的实际参数。
理解,一个类维护一个运行时可接收的消息分发表,分发表中的每个入口是一个方法method,其中可以是一个特定名称,即选择器SEL,其对应一个实现IMP。即指向底层C函数的指针。
还要注意几点
- 总是调用方法的原始实现,不调用原始方法,很有可能影响到程序的其他部分
- 给自定义的方法加前缀,避免方法名冲突
- 理解工作原理
- 小心操作,万一版本一改就??了??了
时间: 2024-10-03 13:48:03