iOS-AOP的简单应用for统计日志

2018-02-06  本文已影响43人  MrPlusZhao

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的扩展类

这个过程比较简单,截图在此,不多解释了

image

2:动态的替换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];
}


上一篇 下一篇

猜你喜欢

热点阅读