美文网首页
iOS Aspects --- AOP(面向切面编程)

iOS Aspects --- AOP(面向切面编程)

作者: MQ_Twist | 来源:发表于2018-12-14 15:00 被阅读151次

人生如梦,一尊还酹江月。

前言

移动端开发常态,忙一阵闲一阵。这不,又到了闲的阶段了,趁还有点闲的时间(产品悄悄对我说,今天下个项目原型通过了,下周开始加班)就赶紧整合之前用到的知识点,一是方便自己以后查阅,二是也方便有需要的iOSer。

Aspects 简介

Aspects是一个简洁高效的用于使iOS支持AOP面向切面编程的库,它可以帮助你在不改变一个类或类实例的代码的前提下,有效更改类的行为。

使用需求

  • ARC
  • 使用iOS 7+和OS X 10.7或更高版本测试方面。

使用场景

  • 统一处理逻辑。
  • 在不改变源码的情况下,插入代码(如无侵染更改第三方库代码,干一些坏坏的事情)

有些小伙伴一看这个库,发现最近更新也是3年前,担心库有问题。听一大牛说,这个库偏底层,只要Apple底层框架不变,那这个库就很稳定。

Aspects github 地址

Aspects 使用

pod search AspectsV1.4.2

该库是轻量级的,接口简单,只有2个方法:

/*
 *    selector: 要hook的目标方法 
 *    AspectOptions: 枚举 
             AspectPositionAfter  //目标方法调用之后走block
             AspectPositionInstead //替换目标方法
             AspectPositionBefore //目标方法之前
             AspectOptionAutomaticRemoval //只实现一次
      block:结合后面的demo看
      error:抛出错误
 *
 *
 *
 */
+ (id<AspectToken>)aspect_hookSelector:(SEL)selector
                           withOptions:(AspectOptions)options
                            usingBlock:(id)block
                                 error:(NSError **)error;

/// Adds a block of code before/instead/after the current `selector` for a specific instance.
- (id<AspectToken>)aspect_hookSelector:(SEL)selector
                           withOptions:(AspectOptions)options
                            usingBlock:(id)block
                                 error:(NSError **)error;

注意:上面2个方法只能hook实例(-)方法,对类(+)方法无效

官方demo

[UIViewController aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo, BOOL animated) {
    NSLog(@"View Controller %@ will appear animated: %tu", aspectInfo.instance, animated);
} error:NULL];

demo上会发现有个AspectInfo,看源码:

@protocol AspectInfo <NSObject>

//返回调用者实例
- (id)instance;
//方法签名信息
- (NSInvocation *)originalInvocation;
//原方法调用的参数
- (NSArray *)arguments;

@end

目前用到:在appDelegate

// 勾取 UIViewController 类所有实例的viewWillAppear: 方法
    [UIViewController aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> info){
        UIViewController *tempVC = (UIViewController *)info.instance;
        NSLog(@">>>%@ viewWillAppear",[tempVC class]);
    } error:nil];
    
    [UIControl aspect_hookSelector:@selector(sendAction:to:forEvent:) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> info){
        UIControl *control = (UIControl *)info.instance;
        if ([control isKindOfClass:[UIButton class]]) {
            UIButton *btn = (UIButton *)control;
            NSLog(@">>>%@",btn.titleLabel.text);
        }
    } error:nil];

实现效果,对所有ViewController的生命周期和button的点击事件进行统计。
由于时间问题,对源码不再详细的阐述,源码用的核心知识点有:

  • 消息转发
  • runtime
  • 自旋锁 (OSSpinLockLock)
  • block的底层结构

后记

目前只是简单的使用,以后有时间了就把源码解析补出来。

相关文章

网友评论

      本文标题:iOS Aspects --- AOP(面向切面编程)

      本文链接:https://www.haomeiwen.com/subject/oncghqtx.html