Objective-C 中的方法混写(Method Swizzling)
by
目录
- 什么是方法混写(Method Swizzling)
- 如何使用方法混写
- 注意事项
- 参考资料
什么是方法混写(Method Swizzling)
Objective-C 中对象调用方法,或者叫“消息传递”,是通过一种动态绑定机制实现的,即对象收到消息后,究竟调用哪个方法,完全于运行期决定,而且方法名和其对应的实现也是可以在运行期改变的,这样,我们不需要源代码,也不用通过继承子类的来覆写方法,就能改变这个类中的方法。这种在运行期改变类的方法实现的手段被称之为方法混写(Method Swizzling).
如何使用方法混写
举一个UIAlertView的例子,UIAlertView 有一个 show 的方法,我们想改变这个 show 的方法,可以按如下实现:
UIAlertView+GHSwizzling.m
#import "UIAlertView+GHSwizzling.h"
#import <objc/runtime.h>
@implementation UIAlertView (GHSwizzling)
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL show = @selector(show);
SEL replaceSHow = @selector(_gh_show);
Method existingMethod = class_getInstanceMethod(self, show);
Method newMethod = class_getInstanceMethod(self, replaceSHow);
method_exchangeImplementations(existingMethod, newMethod);//交换两个方法
});
}
- (void)_gh_show
{
[self _gh_show];
NSLog(@"alert show!");
}
@end
从上面代码我们可以看到,实现方法混写的步骤:
-
编写自己希望实现方法的代码,上述中为
_gh_show
,我们看到 该方法里调用了自己,好像会陷入递归调用的死循环,不过我们需要知道,这个方法是要和show
方法交换的。 -
获取自己实现方法的 method 和原实现方法的 method.
-
通过
method_exchangeImplementations()
函数交换两个方法.
注意: 这只是方法混写中的一种,交换两个实现方法,还有 method_setImplementayion()
等方法.
注意事项
-
方法混写最好在类的 category 中的
+load
方法中进行方法交换. -
方法混写的代码最好在 dispatch_once 中实现。
-
要注意给自己实现的方法加上命名空间,以防止出现重复命名的问题,比如上述中的 “gh” 前缀.
-
不要滥用这个方法,该方法被称之为 Objective-C 中的黑魔法,滥用会导致难以调试的bug.
-
只要在
+load
中实现了method_exchangeImplementations()
, 那么该类的这个方法在整个应用的生命周期以内都被 Swizzling 了,要想调用原来正常的方法,就只能通过调用自己实现的方法名了。
参考资料
Subscribe via RSS