AYAspect 1.0.2

AYAspect 1.0.2

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最新版本2020年1月

Alan Yeh维护。



AYAspect 1.0.2

  • Alan Yeh

AYAspect

CI Status Version License Platform

引用

  使用CocoaPods可以方便地引入AYAspect。在Podfile中添加AYAspect的依赖。

pod "AYAspect"

简介

  在iOS开发中,经常需要引入数据统计、主题应用等。如果在每个ViewController中的viewDidLoad或viewWillAppear等方法进行配置,通常会非常繁琐,同时也不容易维护。

在我编写的过程中,遇到了一些困难,在查找资料时,发现了一些神奇的工具Aspects,但感觉在易用性上,AYAspect更好用一些。

  AYAspect采用极简化的AOP设计,专注于AOP的核心目标,将概念缩减到极致,无需繁复的XML配置。AYAspect提供了两种类型的AOP拦截,可以实现非常强大的AOP功能。

全局拦截

  AYAspect提供全局拦截实现。全局拦截实现只需调用一次,即可对全局所有对象进行拦截。

  以下是代码示例:

    //全局拦截[Teacher save]方法
    [AYAspect interceptSelector:@(save) inClass:[Teacher class] withInterceptor:self];
    //清除Teacher下所有拦截器
    [AYAspect clearInterceptorsForClass:[Teacher class]];
    //清除Teacher下save方法所有拦截器
    [AYAspect clearInterceptsForSelector:@selector(save) inClass:[Teacher class]];

  注意: [AYAspect interceptSelector:inClass:withInterceptor:]不要多次调用,只需调用一次,对全局所有的对象都有效。

实例拦截

  AYAspect可以实现对单个实例进行拦截,而对其他实例没有影响。

  以下是代码示例:

   //拦截一个已存在的实例aTeacher下的save方法
   Teacher *aTeacher = [Teacher new];
   [AYAspect interceptSelector:@selector(save) inInstance:aTeacher withInterceptor:self]

AYInterceptor

AYInterceptor是拦截器协议。拦截器必须实现该协议下的- (void)intercept:(NSInvocation *)invocation方法。

NSInvocation封装了被拦截方法的详细信息,拦截器可以通过操作此实例来达到修改函数调用的目的。

NSInvocation使用

NSInvocation是Apple提供的一种消息调用的方式,由于许多同学对NSInvocation的使用方法并不是非常了解,在此对这类的一些常用用法进行一些解释。

获取/设置参数

   /*
   以[Teacher -loginWithUserName:(NSString *)userName password:(NSString *)pwd为例
   第0个参数是target,第1个参数是SEL,第2个参数才是userName,第3个参数是pwd
   */
   __unsafe_unretained NSString *userName = nil;
   __unsafe_unretained NSString *pwd = nil;
   [invocation getArgument:&userName atIndex:2];
   [invocation getArgument:&pwd atIndex:3];
   
   //设置参数的值
   NSString *newUserName = @"newUserName";
   [invocation setArgument:&newUserName];
   [invocation retainArguments];

目标target

   /*
   以[Teacher -loginWithUserName:(NSString *)userName password:(NSString *)pwd为例
   target即执行-loginWithUserName:password:的对象
   */
   id target = [invocation target];

获取/修改返回值

   /*
   以[Teacher -loginWithUserName:(NSString *)userName password:(NSString *)pwd为例
   target即执行-loginWithUserName:password:的对象
   */
   BOOL isSuccess;
   [invocation getReturnValue:&isSuccess];

   //修改返回值
   BOOL newReturnValue = YES;
   [invocation setReturnValue:&isSuccess];

执行被拦截的函数

   [invocation invoke];

Category

在参考工具Aspect的实现时,发现其实现了一个非常方便的Category方法,因此我也将其整合到我的方案中,以便使用。

   //拦截所有Teacher下面的save方法
   [Teacher ay_interceptSelector:@selector(save) withInterceptor:AYInterceptorMake(^(NSInvocation *invocation) {
        NSLog(@"执行save方法之前做一些事情");
        [invocation invoke];
        NSLog(@"执行save方法之后做一些事情");
    })];
    
    //拦截实例aTeacher下面的save方法
    Teacher *aTeacher = [Teacher new];
    [aTeacher ay_interceptSelector:@selector(save) withInterceptor:AYInterceptorMake(^(NSInvocation *invocation) {
        NSLog(@"执行save方法之前做一些事情");
        [invocation invoke];
        NSLog(@"执行save方法之后做一些事情");
    })];

License

AYAspect遵循MIT许可证。更多信息,请参阅LICENSE文件。