iOS AOP实战
AOP: 面向切面编程,偏向于处理业务的某个阶段
适用场景:
1. 参数校验:网络请求前的参数校验,返回数据的格式校验等等
2. 无痕埋点:统一处理埋点,降低代码耦合度
3. 页面统计:帮助统计页面访问量
4. 事务处理:拦截指定事件,添加触发事件
5. 异常处理:发生异常时使用面向切面的方式进行处理
6. 热修复:AOP可以让我们在某方法执行前后或者直接替换为另一段代码,我们可以根据这个思路,实现bug修复
我们希望将以上需求分离到非业务逻辑的方法中,尽可能的不影响业务逻辑的代码。
demo 从配置AOP到实际应用,有空给咱点个star~
源码分析
0. 类说明
MDAspectInfo:作为对象,包含调用信息(NSInvocation)的对象
作为协议,提供访问对象的属性
MDAspectIdentifier:包含一个hook的信息,调用者,时机,回调处理等
MDAspectTracker:防止重复hook
MDAspectsContainer:通过runtime给被hook的对象添加属性,提供存储和移除hook的方法
MDAspectToken:提供移除hook的协议
1. hook时机
typedef NS_OPTIONS(NSUInteger, MDAspectOptions) {
MDAspectPositionAfter = , /// 默认,当原方法执行完调用
MDAspectPositionInstead = , /// 替换原方法
MDAspectPositionBefore = , /// 原方法执行前调用 MDAspectOptionAutomaticRemoval = << /// Will remove the hook after the first execution.
};
2. 配置文件
配置hook的类,hook时机,实例方法和类方法,以及回调处理
为了区分实例方法和类方法,需要在类方法前加一个“+”
+(NSDictionary *)AOP_MDViewControllerConfigDic{ NSDictionary *configDic = @{
@"MDViewController":@{//hook那个类名
@"TrackEvents":@[
@{//实例方法
@"moment":@"before",//hook之前调用
@"EventSelectorName":@"instanceMethod",//实例方法名
@"block":^(id<MDAspectInfo>aspectInfo){//回调处理
// 获取方法的参数
NSLog(@"跳转");
},
},
@{//类方法
@"moment":@"instead",//替换原方法
@"EventSelectorName":@"+hookClassMethod",//类方法名
@"block":^(id<MDAspectInfo>aspectInfo){//回调处理
// 获取方法的参数
NSLog(@"到处可以hook到我");
},
},
]
},
};
return configDic;
}
3. 解析管理类
// hook到方法回调,完全控制
typedef void (^AspectEventBlock)(id<MDAspectInfo> aspectInfo); @implementation MDAOPManager +(void)load{ // 加载配置文件
NSMutableDictionary *mutableDic = [NSMutableDictionary dictionary];
[mutableDic addEntriesFromDictionary:[MDAOPManager AOP_MDViewControllerConfigDic]];
[mutableDic addEntriesFromDictionary:[MDAOPManager AOP_MDSecViewControllerConfigDic]];
[self configAOPWithDic:mutableDic]; } +(void)configAOPWithDic:(NSDictionary *)configDic{
// 解析配置文件
for (NSString *className in configDic) {
Class clazz = NSClassFromString(className);//拿到类名
NSDictionary *config = configDic[className];//配置信息
NSArray *trackArr = config[@"TrackEvents"];//方法数组
if (trackArr) {
for (NSDictionary *event in trackArr) { AspectEventBlock buttonBlock = event[@"block"];//回调
NSString *method = event[@"EventSelectorName"];//方法名
NSString *moment = event[@"moment"];//hook时机 MDAspectOptions option = MDAspectPositionAfter;
if ([moment isEqualToString:@"before"]) {
option = MDAspectPositionBefore;
}else if ([moment isEqualToString:@"instead"]){
option = MDAspectPositionInstead;
} SEL selector = NSSelectorFromString(method); if ([method hasPrefix:@"+"]) {//hook类方法
method = [method substringFromIndex:];
selector = NSSelectorFromString(method); [clazz aspect_hookClassSelector:selector withOptions:option usingBlock:^(id<MDAspectInfo> aspectInfo) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
buttonBlock(aspectInfo);
});
} error:NULL];
}else{//hook实例方法 [clazz aspect_hookSelector:selector withOptions:option usingBlock:^(id<MDAspectInfo> aspectInfo) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
buttonBlock(aspectInfo);
});
} error:NULL];
}
}
}
}
}
4. 对外接口
// 类直接调用,hook实例方法
+ (id<MDAspectToken>)aspect_hookSelector:(SEL)selector withOptions:(MDAspectOptions)options usingBlock:(id)block error:(NSError **)error;
// 对象调用,hook实例方法
- (id<MDAspectToken>)aspect_hookSelector:(SEL)selector withOptions:(MDAspectOptions)options usingBlock:(id)block error:(NSError **)error;
// 类直接调用,hook类方法
+ (id<MDAspectToken>)aspect_hookClassSelector:(SEL)selector withOptions:(MDAspectOptions)options usingBlock:(id)block error:(NSError *__autoreleasing *)error; // 对象调用,hook类方法
- (id<MDAspectToken>)aspect_hookClassSelector:(SEL)selector withOptions:(MDAspectOptions)options usingBlock:(id)block error:(NSError *__autoreleasing *)error;
说明:MDAspect是对Aspects的扩展,添加了hook类方法的支持,希望能够帮助大家~
iOS AOP实战的更多相关文章
- 包建强的培训课程(11):iOS Runtime实战
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- Cordova - 使用Cordova开发iOS应用实战3(添加Cordova控制台插件)
Cordova - 使用Cordova开发iOS应用实战3(添加Cordova控制台插件) 前文介绍了通过 Safari 的 Web检查器,可以看到控制台输出的信息.但有时这样调试代码不太方便,如果在 ...
- Cordova - 使用Cordova开发iOS应用实战2(生命周期、使用Safari调试)
Cordova - 使用Cordova开发iOS应用实战2(生命周期.使用Safari调试) 前文我们创建了一个简单的Cordova项目,结构如下: 1,Cordova生命周期事件 (1)device ...
- Cordova - 使用Cordova开发iOS应用实战1(配置、开发第一个应用)
Cordova - 使用Cordova开发iOS应用实战1(配置.开发第一个应用) 现在比较流行使用 html5 开发移动应用,毕竟只要写一套html页面就可以适配各种移动设备,大大节省了跨平台应用的 ...
- iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController)
iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController) 前面我们介绍了StoryBoard这个新技术,和纯技术 ...
- iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController)
iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController) 这里我们就直接上实例: 一:新建一个项目singleV ...
- rabbitmq在ios中实战采坑
1. rabbitmq在ios中实战采坑 1.1. 问题 ios使用rabbitmq连接,没过多久就断开,并报错.且用android做相同的步骤并不会报错,错误如下 Received connecti ...
- iOS逆向实战与工具使用(微信添加好友自动确认)
iOS逆向实战与工具使用(微信添加好友自动确认) 原文链接 源码地址 WeChatPlugin-iOS Mac OS 版微信小助手(远程控制.消息防撤回.自动回复.微信多开) 一.前言 本篇主要实现在 ...
- Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序
Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序 C#原本是用来编写Windows以及Windows Phone的应用程序.自从Xamarin问世后.C#的作用就发生了非常大的变化 ...
随机推荐
- Vue全家桶高仿小米商城
大家好,我是河畔一角,时隔半年再次给大家带来一门重量级的实战课程:<Vue全家桶高仿小米商城>,现在很多公司都在参与到商城的构建体系当中,因此掌握一套商城的标准开发体系非常重要:商城的开始 ...
- 用jquery实现楼层滚动对应导航高亮
html 结构排版: // 定位到页面左侧或者右侧 <div class="nav"> <ul id="menu-list"& ...
- POJ 2559 Langest Rectangle in a Histogame
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rec ...
- 什么是RESTful?RESTfule风格
导读 理解什么是REST之前,先去脑补以下什么是HTTP,参考[Http协议] 什么是REST? REST(英文:Representational State Transfer,简称REST,意思:表 ...
- Java中跳出多重嵌套循环的方法
一.使用标号 1.多重嵌套循环前定义一个标号 2.里层循环的代码中使用带有标号 break 的语句 public static void main(String[] args) { ok: for(i ...
- 3- 设置断点修改Response
以下是借鉴别人的知识分享.我在这里转载,如有冒犯,还请告知. 只要你会设置断点修改请求内容的话,这个设置断点修改响应内容的方法也是一样的,只需要修改一下命令即可. 修改响应内容也有两种方法: 第一种: ...
- 如何用css画一个文件上传图案?
如下图,如果是你,你会怎么实现: 通常我们会通过字体图标来显示中间的加号,外层用一个div包裹即可:或者使用伪元素来模拟中间的一横一竖,这都比较麻烦. 其实我们可以直接使用div+css就可以实现. ...
- Python 3 对象关系映射(ORM)
ORM 对象关系映射 Object Relational Mapping 表 ---> 类 字段 ---> 属性 记录 ---> 对象 # mysql_client.py impor ...
- linux,centos,php,word转图片方法
刚开始的时候是客户的活儿,真的是没有想到,被这样一个方法给卡住了,真是醉了,经过漫长的一周,终于搞定了这个问题,以下就来给大家介绍以下这个方法把.能方便大家. (直接转换没办法,所以找了个折中的办法, ...
- 《Java算法》排序算法-快速排序
排序算法-快速排序: /** * 给定一个数组:按照从小到大排序. * 思路: * 1. 获取第一个数放入临时变量data,将大于data的数放右边,小于data的数放在左边. * 2. data左边 ...