简介

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

项目主页: Aspects

最新实例:点击下载

注: AOP是一种完全不同于OOP的设计模式.更多信息,可以参考这里: AOP 百度百科

快速入门

环境要求

  • ARC
  • iOS 7 + 或 OS X 10.7 +

安装

使用 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;
/// 撤销一个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: 调用之后添加观察者;否则可能会引起崩溃.

Aspects– iOS的AOP面向切面编程的库的更多相关文章

  1. Method Swizzling和AOP(面向切面编程)实践

    Method Swizzling和AOP(面向切面编程)实践 参考: http://www.cocoachina.com/ios/20150120/10959.html 上一篇介绍了 Objectiv ...

  2. AOP 面向切面编程, Attribute在项目中的应用

    一.AOP(面向切面编程)简介 在我们平时的开发中,我们一般都是面对对象编程,面向对象的特点是继承.多态和封装,我们的业务逻辑代码主要是写在这一个个的类中,但我们在实现业务的同时,难免也到多个重复的操 ...

  3. AOP面向切面编程的四种实现

     一.AOP(面向切面编程)的四种实现分别为最原始的经典AOP.代理工厂bean(ProxyFacteryBean)和默认自动代理DefaultAdvisorAutoProxyCreator以及Bea ...

  4. Javascript aop(面向切面编程)之around(环绕)

    Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被 ...

  5. [转] AOP面向切面编程

    AOP面向切面编程 AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  6. C# AOP 面向切面编程之 调用拦截

    有时候我们需要在代码中对方法调用进行拦截,并修改参数和返回值,这种操作叫做AOP(面向切面编程) 不过需要注意的是,AOP的效率很慢,在需要高效率场合慎用. 以下是C#的AOP方法: 首先建立一个控制 ...

  7. 【原创】Android AOP面向切面编程AspectJ

    一.背景: 在项目开发中,对 App 客户端重构后,发现用于统计用户行为的友盟统计代码和用户行为日志记录代码分散在各业务模块中,比如在视频模块,要想实现对用户对监控点的实时预览和远程回放行为进行统计, ...

  8. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...

  9. 论AOP面向切面编程思想

    原创: eleven 原文:https://mp.weixin.qq.com/s/8klfhCkagOxlF1R0qfZsgg [前言] AOP(Aspect-Oriented Programming ...

随机推荐

  1. CAD安装失败怎样卸载CAD 2016?错误提示某些产品无法安装

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...

  2. [转]jQueryUI中Datepicker(日历)插件的介绍和使用

    http://jqueryui.com/datepicker/ 本文转自:http://blog.csdn.net/redarmy_chen/article/details/7400571 jQuer ...

  3. (转)Python作业day2购物车

    Python作业day2购物车 原文:https://www.cnblogs.com/spykids/p/5163108.html 流程图: 实现情况: 可自主注册, 登陆系统可购物,充值(暂未实现) ...

  4. JavaScript比较运算符——"== != === !=="区别

    JavaScript的比较和逻辑运算符用于测试 true 或 false. 比较运算符在逻辑语句中使用,以测定变量或值是否相等. 例如给定 x=5,下面的表格解释了比较运算符: 1. == 和===的 ...

  5. nginx虚拟主机配置和反向代理

    虚拟主机有三种配置方式(常用于本机测试使用,将一个ip和端口的请求根据域名不同分配到不同的应用服务器) 基于ip 不常用 基于端口 可选 基于域名 可选 #user nobody; worker_pr ...

  6. pat1052. Linked List Sorting (25)

    1052. Linked List Sorting (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A ...

  7. Active Directory 域服务对象

    局域网计算机控制中心 可以在DC上控制所有局域网资源(计算机 .用户.设备) 大中型企业管理必备. 最后,它还可以让开发人员集成LDAP身份认证,使用域账号登录应用. 也就是说,此企业的所有系统,都可 ...

  8. Quick-Cocos2d-x Lua脚本加密打包器

    准备开新项目了,在寻找合适的框架,后来就发现了Quick-Cocos2d-x这玩意. 别说,还挺好使.之后一步步研究,发现Lua不加密是不行的. 加密的方法在这里. 因为在做版本更新的时候,一般大家都 ...

  9. Oracle11g 卸载教程图解

    1:停掉所有Oracle相关的服务 1.1打开服务方式如下: 1.1.1:右击“计算机”–>管理–>服务和应用程序–>服务 1.1.2:开始–>输入“服务”后点击搜索–> ...

  10. 国外统计学课程主页Statistical Books, Manuals and Journals

    国外统计学课程主页Statistical Books, Manuals and Journalshttp://statpages.info/javasta3.html