V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
kaolalicai
V2EX  ›  问与答

iOS - 面向切面编程(AOP)

  •  
  •   kaolalicai · 2019-09-03 14:19:08 +08:00 · 1171 次点击
    这是一个创建于 1689 天前的主题,其中的信息可能已经有所发展或是发生改变。

    AOP: Aspect Oriented Programming 面向切面编程

    一、什么是 AOP

    • 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
    • AOP 是 OOP 的延续,函数式编程的一种衍生范型

    二、AOP 的优势

    • 对业务逻辑的各个部分进行隔离
    • 降低业务逻辑各部分之间的耦合度
    • 提高程序的可重用性
    • 提高了开发的效率

    三、AOP 在 iOS 的应用 - runtime

    利用 iOS 的runtime,我们可以做很多移花接木的事情,让人首先联想到的就是Method Swizzle,对于Method Swizzle,这里不展开描述,有兴趣的可以自行深入了解

    Aspects

    一个使用起来简单愉快的 iOS AOP 库


    (一)基本用法

    + (id<AspectToken>)aspect_hookSelector:(SEL)selector
                               withOptions:(AspectOptions)options
                                usingBlock:(id)block
                                     error:(NSError **)error;
    
    - (id<AspectToken>)aspect_hookSelector:(SEL)selector
                               withOptions:(AspectOptions)options
                                usingBlock:(id)block
                                     error:(NSError **)error;
    

    AspectPositions

    typedef NS_OPTIONS(NSUInteger, AspectOptions) {
        AspectPositionAfter   = 0,            // 在原始实现后调用(default)
        AspectPositionInstead = 1,            // 将替换原始实现
        AspectPositionBefore  = 2,            // 在原始实现之前调用
        AspectOptionAutomaticRemoval = 1 << 3 // 执行一次后移除 Hook
    };
    

    AspectInfo

    @protocol AspectInfo <NSObject>
    - (id)instance;
    
    - (NSInvocation *)originalInvocation;
    
    - (NSArray *)arguments;
    @end
    

    (二) Aspects 埋点实战

    /** 统计页面的访问量 */
        [UIViewController aspect_hookSelector:@selector(viewDidAppear:)
                                  withOptions:AspectPositionAfter
                                   usingBlock:^(id<AspectInfo> aspectInfo){
                                       dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                                           NSString *className = NSStringFromClass([[aspectInfo instance] class]);
                         [self doSomething];
                                       });
                                   } error:NULL];
    

    (三)使用注意

    • Aspects 使用了 Objective-C 的消息转发机会,会有一定的性能消耗,所有对于过于频繁的调用,不建议使用 Aspects
    • 当应用于某个类时(使用类方法添加钩子),不能同时 hook 父类和子类的同一个方法,否则会引起循环调用问题;但是当应用于某个类的示例时(使用实例方法加钩子),不受此限制。
    • 使用 KVO 时,最好在 aspect_hookSelector: 调用之后添加观察者,否则可能会引起崩溃
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   955 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 22:00 · PVG 06:00 · LAX 15:00 · JFK 18:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.