您的位置:首页 > 其它

OC- Method Swizzling

2016-03-12 20:12 309 查看
1、Method Swizzling 原理

Objective-C 的每一个方法都有一个唯一对应的SEL,而方法是运行时绑定的,利用这些特性,我们可以在运行时调换方法的实现。前面我们说过,IMP 是一个函数指针,通过SEL获得指向方法的入口地址。下面是正常情况下SEL对应IMP函数指针的情况:



Method Swizzling 实现的原理就是调换IMP的指向:



2、Method Swizzling 应用

#import "UIViewController+MethodSwizzling.h"
#include <objc/runtime.h>

@implementation UIViewController (MethodSwizzling)

/*
+load 方法会在类加入运行期调用,这是把方法调配放在+load方法里面的原因
*/
+ (void)load
{
static dispatch_once_t onceToken;
/*单例保证并行情况下不会有问题*/
dispatch_once(&onceToken, ^{
Class class = [self class];

SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(my_viewWillAppear);

/*获取原来的方法*/
Method originalMethod = class_getInstanceMethod(class, originalSelector);
/*获取要替换的方法*/
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

/*originalSelector是否有实现,如果存在返回YES,不存在返回NO*/
BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (success)
{
/*修改要替换的方法实现为原有实现*/
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else
{
/*表示待交换的两个方法的实现*/
method_exchangeImplementations(originalMethod, swizzledMethod);
}

});
}

#pragma mark - Method Swizzling
/*
看上去会递归调用,进入死循环。但是这个方法是准备和viewWillAppear方法交换的。在运行期,my_viewWillAppear 选择子实际上对应于原有的viewWillAppear方法实现。
*/
- (void)my_viewWillAppear
{
[self my_viewWillAppear];
NSLog(@"%s", __func__);
}

@end


3、注意事项

1、在+load方法中使用;

2、命名规范,带前缀;

3、在dispatch_once中执行,保证代码不管在多少个线程情况下,只被执行一次。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: