美文网首页项目开发技巧程序员iOS 开发
Aspects iOS的AOP面向切面编程的库

Aspects iOS的AOP面向切面编程的库

作者: 门前有棵葡萄树 | 来源:发表于2016-03-24 17:20 被阅读423次

简介
一个简洁高效的用于使iOS支持AOP面向切面编程的库.它可以帮助你在不改变一个类或类实例的代码的前提下,有效更改类的行为.比iOS传统的 AOP方法,更加简单高效.支持在方法执行的前/后或替代原方法执行.曾经是 PSPDFKit 的一部分,PSPDFKit,在Dropbox和Evernote中都有应用,现在单独单独开源出来给大家使用.

安装
使用 CocoaPods 安装
pod "Aspects"

手动安装
把文件Aspects.h/m
拖到工程中即可.

用法
应用场景
Aspects 用于支持AOP(面向切面编程)模式,用于部分解决OOP(面向对象)模式无法解决的特定问题.具体指的是那些在多个方法有交叉,无法或很难被有效归类的操作,比如:
不论何时用户通过客户端获取服务器端数据,权限检查总是必须的.不论何时用户和市场交互,总应该更具用户的操作提供相应地购买参考或相关商品.所有需要日志记录的操作.
接口概述
Aspects 给 NSObject 扩展了下面的方法:
/// 为一个指定的类的某个方法执行前/替换/后,添加一段代码块.对这个类的所有对象都会起作用.////// @param block 方法被添加钩子时,Aspectes会拷贝方法的签名信息./// 第一个参数将会是 id<AspectInfo>,余下的参数是此被调用的方法的参数./// 这些参数是可选的,并将被用于传递给block代码块对应位置的参数./// 你甚至使用一个没有任何参数或只有一个id<AspectInfo>参数的block代码块.////// @注意 不支持给静态方法添加钩子./// @return 返回一个唯一值,用于取消此钩子.+ (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; - (id<AspectToken>)aspect_hookSelector:(SEL)selector withOptions:(AspectOptions)options usingBlock:(id)block error:(NSError **)error; /// 撤销一个Aspect 钩子./// @return YES 撤销成功, 否则返回 NO. id<AspectToken> aspect = ...; [aspect remove];

所有的调用,都会是线程安全的.Aspects 使用了Objective-C 的消息转发机会,会有一定的性能消耗.所有对于过于频繁的调用,不建议使用 Aspects.Aspects更适用于视图/控制器相关的等每秒调用不超过1000次的代码.
代码示例
可以在调试应用时,使用Aspects动态添加日志记录功能.
[UIViewController aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo, BOOL animated) { NSLog(@"控制器 %@ 将要显示: %tu", aspectInfo.instance, animated);} error:NULL];

使用它,分析功能的设置会很简单:https://github.com/orta/ARAnalytics
你可以在你的测试用例中用它来检查某个方法是否被真正调用(当涉及到继承或类目扩展时,很容易发生某个父类/子类方法未按预期调用的情况):

  • (void)testExample { TestClass *testClass = [TestClass new]; TestClass *testClass2 = [TestClass new]; __block BOOL testCallCalled = NO; [testClass aspect_hookSelector:@selector(testCall) withOptions:AspectPositionAfter usingBlock:^{ testCallCalled = YES; } error:NULL]; [testClass2 testCallAndExecuteBlock:^{ [testClass testCall]; } error:NULL]; XCTAssertTrue(testCallCalled, @"调用testCallAndExecuteBlock 必须调用 testCall");}

它对调试应用真的会提供很大的作用.这里我想要知道究竟何时轻击手势的状态发生变化(如果是某个你自定义的手势的子类,你可以重写setState:方法来达到类似的效果;但这里的真正目的是,捕捉所有的各类控件的轻击手势,以准确分析原因):
[_singleTapGesture aspect_hookSelector:@selector(setState:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) { NSLog(@"%@: %@", aspectInfo.instance, aspectInfo.arguments);} error:NULL];

下面是一个你监测一个模态显示的控制器何时消失的示例.通常,你也可以写一个子类,来实现相似的效果,但使用 Aspects 可以有效减小你的代码量:
@implementation UIViewController (DismissActionHook)// Will add a dismiss action once the controller gets dismissed.- (void)pspdf_addWillDismissAction:(void (^)(void))action { PSPDFAssert(action != NULL); [self aspect_hookSelector:@selector(viewWillDisappear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) { if ([aspectInfo.instance isBeingDismissed]) { action(); } } error:NULL];}@end

对调试的好处
Aspectes 会自动标记自己,所有很容易在调用栈中查看某个方法是否已经调用:



在返回值不为void的方法上使用 Aspects
你可以使用 NSInvocation 对象类自定义返回值:
[PSPDFDrawView aspect_hookSelector:@selector(shouldProcessTouches:withEvent:) withOptions:AspectPositionInstead usingBlock:^(id<AspectInfo> info, NSSet *touches, UIEvent *event) { // 调用方法原来的实现. BOOL processTouches; NSInvocation *invocation = info.originalInvocation; [invocation invoke]; [invocation getReturnValue:&processTouches]; if (processTouches) { processTouches = pspdf_stylusShouldProcessTouches(touches, event); [invocation setReturnValue:&processTouches]; } } error:NULL];

兼容性与限制
当应用于某个类时(使用类方法添加钩子),不能同时hook父类和子类的同一个方法;否则会引起循环调用问题.但是,当应用于某个类的示例时(使用实例方法添加钩子),不受此限制.使用KVO时,最好在aspect_hookSelector:
调用之后添加观察者;否则可能会引起崩溃.

原文https://segmentfault.com/a/1190000003499895

相关文章

  • iOS 面向切面(AOP)编程 —— Aspects & Blo

    参考 iOS 面向切面(AOP)编程 —— Aspects & BlockHook

  • iOS Aspects的实现原理

    Aspects是iOS上技巧性很强的一个第三方类库,主要针对于AOP编程(面向切面编程)的思想。 “面向切面编程”...

  • iOS开发AOP框架Aspects源码分析

    Aspects解决的问题 Aspects是AOP(面向切面编程)思想在iOS下OC的实现。Aspects可以用于h...

  • AOP编程简述

    iOS AOP (面向切面编程) AOP面向切面编程(也叫面向方面):Aspect Oriented Progra...

  • Aspects 源码解析

    简介 Aspects是一个轻量的面向切面编程(AOP)的第三方库,面向切面编程简单来说,就是在原来的业务流程之中的...

  • 优秀第三方框架

    Aspects 使用方法一个简洁高效的用于使iOS支持AOP面向切面编程的库.它可以帮助你在不改变一个类或...

  • Aspects解析

    Aspects AOP(Aspect-oriented programming) 面向切面编程 通过预编译方式和运...

  • iOS获取当前的ViewController

    更新:之前的代码,或多或少有些问题。现改用Aspects获取当前的vc。Aspects是AOP(面向切面编程)思想...

  • iOS Aspects源码剖析

    摘要:Aspects用来干什么?Aspect是一个简洁高效的用于使iOS支持AOP(面向切面编程)的框架。官方描述...

  • iOS开源类库:Runtime

    https://github.com/steipete/Aspects 交换两个方法的实现 AOP(面向切面编程)...

网友评论

本文标题:Aspects iOS的AOP面向切面编程的库

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