Method类型是一个objc_method结构体指针,而结构体objc_method有三个成员,方法交换(Method Swizzling)的本质就是更改两个成员method_types和method_imp
/// An opaque type that represents a method in a class definition.typedefstructobjc_method *Method;// 本质是一个结构体structobjc_method {
SEL method_name;// 方法名称
char*method_types;// 参数和返回类型的描述字串
IMP method_imp;// 方法的具体的实现的指针}
上一段swizzle的代码:
+ (void)load{
staticdispatch_once_tonceToken;
dispatch_once(&onceToken, ^{
Classclass = [selfclass];
// 原方法名和替换方法名
SELoriginalSelector =@selector(viewDidAppear:);
SELswizzledSelector =@selector(swizzle_viewDidAppear:);
// 原方法结构体和替换方法结构体
MethodoriginalMethod =class_getInstanceMethod(class, originalSelector);
MethodswizzledMethod =class_getInstanceMethod(class, swizzledSelector);
// 如果当前类没有原方法的实现IMP,先调用class_addMethod来给原方法添加默认的方法实现IMP
BOOLdidAddMethod =class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {// 添加方法实现IMP成功后,修改替换方法结构体内的方法实现IMP和方法类型编码TypeEncoding
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
}else { // 添加失败,调用交互两个方法的实现
method_exchangeImplementations(originalMethod, swizzledMethod);
}
method_exchangeImplementations(originalMethod, swizzledMethod);
});
}
question1: swizzled 交换的本质是什么?
是method_imp的交换,由SEL查找对应的method_imp改变了。
question2: swizzled 交换为什么还要调用class_addMethod?
以上述代码为例子,如果本类没有实现swizzle_viewDidAppear,就会去向上查找父类是否实现swizzle_viewDidAppear。如果一直向上查上去没有实现过swizzle_viewDidAppear,就会崩溃。