iOS 方法交换(methodSwizzling)
2017-11-24 本文已影响155人
uniapp
iOS运行中runtime中采用消息分发机制,允许开发者对其进行方法交换,替换某个类的方法实现或者在执行方法前添加自定义内容,控制App的执行流程。实现方式可以参考如下两篇:
Runtime Method Swizzling 开发实例汇总(持续更新中)
iOS中的黑魔法:Method Swizzling
下面方法交换中令人迷惑的if/else进行详细解释:
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method originalMethod = class_getInstanceMethod([self class], @selector(originalMethod));
Method swizzlingMethod = class_getInstanceMethod([self class], @selector(swizzlingMethod));
BOOL isAdded = class_addMethod([self class], method_getName(originalMethod), method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
//添加不存在的方法,返回Yes;
// Method originalMethodTest = class_getInstanceMethod([self class], @selector(originalMethodTest));
// BOOL isAddedTest = class_addMethod([self class], method_getName(originalMethodTest), method_getImplementation(originalMethodTest), method_getTypeEncoding(originalMethod));
if (isAdded)
{
NSLog(@"方法在原类中不存在,已经添加成功,用下面的方法替换其实现");
class_replaceMethod([self class], method_getName(originalMethod), method_getImplementation(swizzlingMethod), method_getTypeEncoding(swizzlingMethod));
}
else
{
NSLog(@"方法在原类中存在,用下面的方法交换其实现方法");
method_exchangeImplementations(originalMethod, swizzlingMethod);
}
NSLog(@"end");
});
}
- (void)originalMethod{
NSLog(@"原类中的方法");
}
- (void)swizzlingMethod{
NSLog(@"替换过的方法");
}
先明确以下知识点:
ObjectClass中方法的区分基于方法名称name和有无参数variable区分方法是否一样。
//1
- (void)originalMethod{
NSLog(@"原类中的方法");
}
//2
- (void)originalMethod:(NSString *)name{
NSLog(@"原类中的方法");
}
//3
- (void)originalMethod:(int)count{
NSLog(@"原类中的方法");
}
1和2是不同的方法,2和3是同一个方法;
文档中对class_addMethod的解释如下:
* @return YES if the method was added successfully, otherwise NO
* (for example, the class already contains a method implementation with that name).
*
* @note class_addMethod will add an override of a superclass's implementation,
* but will not replace an existing implementation in this class.
* To change an existing implementation, use method_setImplementation.
*/
OBJC_EXPORT BOOL
class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp,
const char * _Nullable types)
添加成功返回Yes,否则返回No。也就是说用class_addMethod添加类中不存在的方法(方法名或者参数不一致)时,返回Yes。然后可以用class_replaceMethod方法替换实现方式,如果放回No表明原类中已经定义了方法实现,需要调用method_exchangeImplementations交换实现方式。
喜欢和关注都是对我的鼓励和支持~