iOS中AOP与Method Swizzling 项目中的应用
引子:项目中需要对按钮点击事件进行统计分析,现在项目中就是在按钮的响应代码中添加点击事件,非常繁琐。所以使用了AOP(面向切面编程),将统计的业务逻辑统一抽离出来。
项目中添加的开源库:https://github.com/steipete/Aspects
Method Swizzling 利用runtime交换了函数 SEL A,IMP A 与 SEL B,IMP B,这一黑魔法使得抽离业务逻辑变的可能。
更多资料可以参考:http://www.cocoachina.com/ios/20150120/10959.html
我处理的过程是新建了一个类用于处理AOP,暂且叫Aspect类
+ (void)load {
[super load];
[Aspect sharedInstance];
}
+ (instancetype)sharedInstance {
static CGAspect *_shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_shared = [[CGAspect alloc] init];
});
return _shared;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self CG_hook_UIButton];
}
return self;
}
-(void)CG_hook_UIButton {
[UIButton aspect_hookSelector:@selector(sendAction:to:forEvent:) withOptions:0 usingBlock:^(id<AspectInfo> info) {
UIButton *btn = [info instance];
NSString *str = btn.buriedPointTag;
if (str.length > 0) {
//在这里处理统计的模块
}
} error:NULL];
}
主要说明一下hook的方法,apects对hook有了很好的封装,第一参数是需要hook的SEL,第二个参数是一个枚举状态,表示你所hook得方法与第三个参数(block)的执行顺序,具体可以参见枚举说明。第三个block参数中可以获取到info,通过 [info instance]可以获取到调用的实例对象,在这里是个button。
btn.buriedPointTag的属性是专门用来处理统计的按钮的标签,当然你也可以用原生的tag标签,我这里主要是为了完全抽离这里的逻辑。
以下是为button添加buriedPointTag的方法
- (NSString *)buriedPointTag
{
return objc_getAssociatedObject(self, UIButton_buriedPoint_key);
}
- (void)setBuriedPointTag:(NSString *)buriedPointTag
{
objc_setAssociatedObject(self, UIButton_buriedPoint_key, buriedPointTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
这样就轻松的把按钮的统计做好,当然你的产品要对别的控制也做统计,你仍然需要去额外处理,你也可以用这种方法对别的类型的统计业务进行抽离,具体情况需要看需求有没有必要这么处理。
iOS中AOP与Method Swizzling 项目中的应用的更多相关文章
- ios逆向工程-内部钩子(Method Swizzling)
Method Swizzling(方法调配) 怎么说呢,先了解什么是钩子为什么用钩子,学过C++的朋友应该清楚,hook就是用来获得(截断/改变)底层调用的方法.这样我们可以自由的修改或者读取一些想要 ...
- JS中的位操作在实际项目中的应用
前言: Linux中的文件管理子系统的权限管理,想必大家都知道:rwx分别代表read(可读),write(可写), execute(可执行,如果是可执行程序的话),其中rxw可以按照数字表示: r ...
- Eclipse中定位当前文件在项目中的位置
点击红色框内的按钮,就能定位当前文件在项目中的位置, 另外, 找到位置后记得再点击一下这个按钮, 要不然每次打开一个文件都会自动定位
- idel 中 生成 jar包 和项目中自己需要的包
一.首先在自己的项目中创建一个类类中创建一个构造方法构造方法中传入一个字符串参数(这个字符串参数是为了传入路径) 在方法体内通过file类创建文件夹(换而言之就是项目中的包) 二 .就是对这个项目中的 ...
- 项目中使用express,只是单纯项目中使用
安装express npm install express --save-dv 建议安装到dev依赖里面 安装body-parse npm install body-parser --save-dev ...
- 使用AOP和Semaphore对项目中具体的某一个接口进行限流
整体思路: 一 具体接口,可以自定义一个注解,配置限流量,然后对需要限流的方法加上注解即可! 二 容器初始化的时候扫描所有所有controller,并找出需要限流的接口方法,获取对应的限流量 三 使用 ...
- Eclipse中使用maven构建web项目中遇到的问题
构建过程参考: http://blog.csdn.net/smilevt/article/details/8215558/ http://www.cnblogs.com/dcba1112/archiv ...
- 理解css中Grid布局,在项目中如何实现grid页面布局
简介 CSS中Grid是一种二维网格式布局方式.我们常规使用table.float.position.inline-block等布局,但它们遗漏了很多功能,例如垂直居中.后来css3中flexbox的 ...
- 通过iframe引入另外一个项目中的html片段到项目中,解决样式,高度,兼容等问题的策略
<!--尾部开始--> <iframe src="http://172.16.24.11:9000/cartoon-web/footer_new" m ...
随机推荐
- InteropBitmap指定内存,绑定WPF的Imag控件时刷新问题。
1.InteropBitmap指定内存,绑定WPF的Imag控件的Source属性 创建InteropBitmap的时候,像素的格式必须为PixelFormats.Bgr32, 如果不是的话在绑定到I ...
- linux 内核 RCU机制详解
RCU(Read-Copy Update)是数据同步的一种方式,在当前的Linux内核中发挥着重要的作用.RCU主要针对的数据对象是链表,目的是提高遍历读取数据的效率,为了达到目的使用RCU机制读取数 ...
- linux修改ip地址的方法
1. 临时设置ip地址 ifconfig eth0 IP地址 (网络掩码和网关如果不设置就使用默认0) 这种方法只是临时修改,重启网卡或服务器又会还原 2.使用vi编辑器设置 1122.www.qix ...
- React Native 开发之 (06) JSX
一 React 1 React定义 React的GitHub地址是 https://github.com/facebook/react.它的官方介绍是 A JavaScript Library for ...
- JS-DOM 综合练习-动态添加删除班级成绩表
费了2个小时,才把原理弄懂,把问题逐个解决,当你发现你最后栽的那个点,是一个小石头拌的你,你起来是该哭还是该笑呢?只怪自己习武不精吧. 虽然问题都解决了,但是还有一个余留的问题就是鼠标经过input时 ...
- [中英双语] 数学缩写列表 (List of mathematical abbreviations)
List of mathematical abbreviations From Wikipedia, the free encyclopedia 数学缩写列表 维基百科,自由的百科全书 This ar ...
- spark操作geoip的domain数据库
val ipv4 = sc.textFile("hdfs://hbase11:9000/sparkTsData/GeoIP2-Domain-Blocks-IPv4.csv").ma ...
- Linux下安装setup tools小工具
1, 最小化的linux系统(centos\redhat)默认都是没有安装setup图形小工具的,你输入setup命令会提示 command not found . 如果要使用这个命令安装方法 1.安 ...
- JavaScript格式化日期
查找格式化日期的方法大都是写日期扩展方法,也许是为了维持jquery easyUI 源码完整性, // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h ...
- 10月16日下午MySQL数据库CRUD操作(增加、删除、修改、查询)
1.MySQL注释语法--,# 2.2.后缀是.sql的文件是数据库查询文件. 3.保存查询. 关闭查询时会弹出提示是否保存,保存的是这段文字,不是表格(只要是执行成功了表格已经建立了).保存以后下次 ...