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

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

前言

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

后记

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Oracle笔记系列这几篇是来自一位老师的笔记,分享给大家放在简书上,主要方便自己时常复习,还有学习Oracle的...
    panda_Hi阅读 945评论 0 0
  • #五五开封号# 一早醒来,手机就被五五开刷屏了,网友评论也是一波的随风倒,颇有一股子“君子报仇十年不晚”的豪气,很...
    木阿桑阅读 337评论 1 0
  • 终于,在广州一个寒冷的冬夜里,我读完了《最好的告别》(Being Mortal)这本书,一本由美国医生阿图·葛文德...
    筱慕雪阅读 15,045评论 2 2
  • 我很荒唐 这个世界没有上帝 世界也只是名词 我很荒唐 没有人规定荒唐的人不能做什么 人也是个名词 我很荒唐 荒唐是...
    盲码阅读 189评论 0 1