AOP(what ? ) :
首先我们来简单的解释一下AOP(面向切面编程)
(个人觉得这个回答比较好:https://www.zhihu.com/question/24863332)
简单来讲就是在运行时(要涉及到Runtime的方法),动态的将代码切入到类的指定方法,指定位置上.这样的编程思想就是面向切面编程,我理解的它的优点是: 1:降低代码复杂度,提高开发效率 2:一定程度上有效减少代码耦合性
实际应用:
此处附上Demo地址:https://github.com/MrPlusZhao/ZTPMethodExchange
假如有这样一个需求,运营要求我们的APP统计每一个页面的访问频率数据,那么我们就需要程序在运行时,有一个触发点来和后台进行沟通,记录访问该页面的次数,现在我们就针对UIViewController的WillDidAppear方法作为沟通入口,进行无侵入式的操作
思路是这样:
1:创建一个UIViewController的扩展类
2:动态的替换WillDidAppear的实现方法
3:在WillDidAppear里面和后台进行数据传输
1:创建一个UIViewController的扩展类
这个过程比较简单,截图在此,不多解释了
image2:动态的替换WillDidAppear的实现方法
这个过程比较重要我们需要用的Runtime(如果Runtime有点迷糊的小伙伴请猛戳这里https://www.cnblogs.com/ioshe/p/5489086.html)
要使用Runtime方法,头文件需要引入#import<objc/message.h>
@implementation UIViewController (Statistics)
+ (void)load
{
[self ZTPMethodSwizzing:self methodOld:@selector(viewDidAppear:) methodNew:@selector(ZTP_WillDidAppear:)];
}
BuildSetting里面开启权限
要动态修改方法,我们必须要先拿到这个方法,Runtime有一个方法是
class_getInstanceMethod
//用法如下,用Runtime的方法,先要去 BuildSetting里面开启权限 截图在上面
把Enable Strict Checking.......设置成NO
//思路是,
//1.先获取原来的方法,再获取新的方法,然后进行替换
/**2:若UIViewController类没有该方法,那么它会去UIViewController的父类去寻找,为了避免不必要的麻烦,我们先进行一次添加
*/
//3: 如果原来类没有这个方法,可以成功添加,如果原来类里面有这个方法,那么将会添加失败
//最后就是你新写的方法里面实现你要做的事情
#import "UIViewController+Statistics.h"
#import <objc/message.h>
@implementation UIViewController (Statistics)
+ (void)load
{
[self ZTPMethodSwizzing:self methodOld:@selector(viewDidAppear:) methodNew:@selector(ZTP_WillDidAppear:)];
}
+ (void)ZTPMethodSwizzing:(Class)className methodOld:(SEL)oldMethod methodNew:(SEL)newMethod
{
//1:先拿到这两个方法
Method originalMethod = class_getInstanceMethod(className, oldMethod);
Method swizzledMethod = class_getInstanceMethod(className, newMethod);
/**2:若UIViewController类没有该方法,那么它会去UIViewController的父类去寻找,为了避免不必要的麻烦,我们先进行一次添加
*/
BOOL AddMethod = class_addMethod(className, oldMethod, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
//3: 如果原来类没有这个方法,可以成功添加,如果原来类里面有这个方法,那么将会添加失败
if (AddMethod) {
class_replaceMethod(className, oldMethod, class_getMethodImplementation(className, newMethod), method_getTypeEncoding(swizzledMethod));
}
else
{
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
- (void)ZTP_WillDidAppear:(BOOL)isAnimation
{
[self ZTP_WillDidAppear:isAnimation];
NSString * namestr = NSStringFromClass([self class]);
NSLog(@"do something for statics in class %@",namestr);
//如果项目中集成了友盟统计,那么就可以在此处实现
// [MobClick beginLogPageView:namestr];
}
网友评论