Skip to content

Instantly share code, notes, and snippets.

@zhangkn
Last active May 3, 2018 09:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhangkn/aa1e1704963fbd4b7e6cd1dcf4ab07e5 to your computer and use it in GitHub Desktop.
Save zhangkn/aa1e1704963fbd4b7e6cd1dcf4ab07e5 to your computer and use it in GitHub Desktop.
友盟统计模块的例子,使用Swizzle;---在系统提供的方法上再扩充功能时(不能重写系统方法),就可以使用`Method Swizzling`.
//可以用于日志记录和 Mock 测试。例如上报用户打开的界面所在VC的名称,就可以使用swizzling 统一处理
void Swizzle(Class c, SEL orig, SEL new) {
Method origMethod = class_getInstanceMethod(c, orig);
Method newMethod = class_getInstanceMethod(c, new);
if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))//给一个方法添加新的方法和实现;Adds a new method to a class with a given name and implementation.
//若返回Yes说明类中没有该方法,然后再使用 `class_replaceMethod()` 方法进行取代
class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));//取代了对于一个给定类的实现方法
else
//YES if the method was added successfully, otherwise NO (for example, the class already contains a method implementation with that name).
method_exchangeImplementations(origMethod, newMethod);//交换两个类的实现方法
}
//当类加载之后,会调用一个名为 load 的类函数
+ (void)load{//不会碰到并发问题。
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{//由于我们只打算混淆一次,因此我们需要使用 dispatch_once
Swizzle([UIViewController class], @selector(viewWillAppear:), @selector(autolog_viewWillAppear:));
Swizzle([UIViewController class], @selector(viewWillDisappear:), @selector(autolog_viewWillDisAppear:));
Swizzle([UIViewController class], @selector(presentViewController:animated:completion:), @selector(autoLog_presentViewController:animated:completion:));
Swizzle([UIViewController class], @selector(dismissViewControllerAnimated:completion:), @selector(autoLog_dismissViewControllerAnimated:completion:));
});
}
-(void)autolog_viewWillDisAppear:(BOOL)animated{
if (![self isKindOfClass:[UINavigationController class]] && ![self isKindOfClass:[UITabBarController class]] && ![self isKindOfClass:[xxx class]] && ![self isKindOfClass:[xx class]]) {
[MobClick endLogPageView:NSStringFromClass([self class])];//友盟统计模块
}
[self autolog_viewWillDisAppear:animated];//看似会陷入递归调用,
//其实则不会,因为我们已经在`+ (void)load `方法中更换了`IMP`,他会调用`viewWillDisAppear:`方法,然后在后面添加我们需要添加的功能。
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment