Objective-C Method Swizzling增强注释版。有些代码可能拿过来能直接用,但是我们并不知道其原理或者理解想法,所以总是一知半解。昨天看了下Objective-C Method Swizzling,这是很典型的案例,因为很绕!(只有我觉得绕吗?看着看着自己就懵了[手动一脸懵逼]),所以自己加了点注释,帮助下理解(可能理解的不对,大家不吝赐教吧!)
我理解的哈~:重点就是方法名和方法的实现 我们要区别开 - (void)...; 是方法的声明 - (void)...{}这个是方法的实现,交换方法的原理其实就是维持方法申明不变,然后交换两个方法的实现,引起的结果就是 调用a方法:[... a],而实际上调用的是b方法的实现:-b{},反之亦然。
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class]; //替换的是对象(实例)方法
//!重点强调下 如果替换的是类方法 格式应该是
Class class = object_getClass[self class];
// SEL originalSelector = @selector(viewWillAppear:);
// SEL swizzledSelector = @selector(mrc_viewWillAppear:);
SEL originalSelector = @selector(log);
SEL swizzledSelector = @selector(customLog);
//对象方法替换
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
//类方法替换
Method originalClassMethod = class_getClassMethod(class, originalSelector);
Method swizzledClassMethod = class_getClassMethod(class, swizzledSelector);
///----------------------------------------
/// @name 最核心需要理解的代码
///----------------------------------------
BOOL success =
class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
// class_addMethod 为originalSelector方法添加实现 成功:说明该方法没有在.m中实现 于是就把swizzledMethod的实现添加给了originalSelector 失败:说明该方法有在.m中实现了 那么就将两个方法的实现进行替换 注意 是替换实现 而不是方法名
//Method 组成是个结构体 成分:SELname:方法名; constchar*types:参数; IMPimp:实现;
//class_addMethod照我的理解 就是添加一个结构体,然后给SEL和IMPimp赋值,所以这里其实也是给originalSelector替换好了实现(成功success=yes)
//success 作用:
//如果返回YES 说明这个类.m没有实现了这个方法(那么肯定是父类实现了)这里我之前有个疑问,如果originalMethod
一直没有实现,或者都不存在呢?那下面的class_replaceMethod导致的后果难道不是奔溃吗?因为你用了一个不存在的实现去替换另一个方法的声明,一调用不是炸了?后来我想了想,originalMethod不存在我们也没法调用对不对,替换了有怎么样?我们没法去调用呀!originalMethod只声明不实现呢?那肯定奔溃呀!这不很正常么~"茅厕顿开"
if (success) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
//如果返回NO 说明这个类.m实现了这个方法
else {
method_exchangeImplementations(originalMethod, swizzledMethod);//交换两个方法的实现
//e.g 调mrc_viewWillAppear方法,联动的是viewWillAppear的实现
//调viewWillAppear方法,联动的是的实现mrc_viewWillAppear
}
NSLog(@"loadReady");
});
}
#pragma mark - Method Swizzling
//重点在这,乍一看不是循环调用了吗?要记住一点 方法的声明和方法的调用不是一个概念
- (void)customLog{//这是方法的实现
[self customLog];//这是通过方法的声明调用对应方法的实现 而在这里customLog方法的实现已经被我们替换掉了
NSLog(@"====");
}