Method Swizzling和AOP(面向切面编程)实践
2015-10-19 18:00
344 查看
Method Swizzling和AOP(面向切面编程)实践
参考: http://www.cocoachina.com/ios/20150120/10959.html上一篇介绍了 Objective-C Messaging。利用 Objective-C 的 Runtime 特性,我们可以给语言做扩展,帮助解决项目开发中的一些设计和技术问题。这一篇,我们来探索一些利用 Objective-C Runtime 的黑色技巧。这些技巧中最具争议的或许就是 Method Swizzling 。
介绍一个技巧,最好的方式就是提出具体的需求,然后用它跟其他的解决方法做比较。
所以,先来看看我们的需求:对 App 的用户行为进行追踪和分析。简单说,就是当用户看到某个 View 或者点击某个 Button 的时候,就把这个事件记下来。
手动添加
最直接粗暴的方式就是在每个 viewDidAppear 里添加记录事件的代码。
你可能会想到用继承或者类别,在重写的方法里添加事件记录的代码。比如用类别的代码大概长这个样子:
1.你需要继承 UIViewController, UITableViewController, UICollectionViewController 所有这些 ViewController ,或者给他们添加类别;
2.每个 ViewController 里的 ButtonClick 方法命名不可能都一样;
3.你不能控制别人如何去实例化你的子类;
4.对于类别,你没办法调用到原来的方法实现。大多时候,我们重写一个方法只是为了添加一些代码,而不是完全取代它。
5.如果有两个类别都实现了相同的方法,运行时没法保证哪一个类别的方法会给调用。
Method Swizzling
Method Swizzling 利用 Runtime 特性把一个方法的实现与另一个方法的实现进行替换。
上一篇文章有讲到每个类里都有一个 Dispatch Table ,将方法的名字(SEL)跟方法的实现(IMP,指向 C 函数的指针)一一对应。Swizzle 一个方法其实就是在程序运行时在 Dispatch Table 里做点改动,让这个方法的名字(SEL)对应到另个 IMP 。
首先定义一个类别,添加将要 Swizzled 的方法:
接下来实现 swizzle 的方法 :
最后,我们只需要确保在程序启动的时候调用 swizzleMethod 方法。比如,我们可以在之前 UIViewController 的 Logging 类别里添加 +load: 方法,然后在 +load: 里把 viewDidAppear 给替换掉:
其实,这里还可以更简化点:直接用新的 IMP 取代原 IMP ,而不是替换。只需要有全局的函数指针指向原 IMP 就可以。
而像上面例子用 Method Swizzling 动态给指定的方法添加代码,以解决 Cross Cutting Concerns 的编程方式叫:Aspect Oriented Programming
Aspect Oriented Programming (面向切面编程)
Wikipedia 里对 AOP 是这么介绍的:
An aspect can alter the behavior of the base code by applying advice (additional behavior) at various join points (points in a program) specified in a quantification or query called a pointcut (that detects whether a given join point matches).
在 Objective-C 的世界里,这句话意思就是利用 Runtime 特性给指定的方法添加自定义代码。有很多方式可以实现 AOP ,Method Swizzling 就是其中之一。而且幸运的是,目前已经有一些第三方库可以让你不需要了解 Runtime ,就能直接开始使用 AOP 。
Aspects 就是一个不错的 AOP 库,封装了 Runtime , Method Swizzling 这些黑色技巧,只提供两个简单的API:
利用 objective-C Runtime 特性和 Aspect Oriented Programming ,我们可以把琐碎事务的逻辑从主逻辑中分离出来,作为单独的模块。它是对面向对象编程模式的一个补充。Logging 是个经典的应用,这里做个抛砖引玉,发挥想象力,可以做出其他有趣的应用。
使用 Aspects 完整的例子可以从这里获得:AspectsDemo。
如果你有什么问题和想法,欢迎留言或者发邮件给我 peng@glowing.com 进行讨论。
Reference
method-swizzling
method replacement for fun and profit
Aspects
相关文章推荐
- vsftpd 服务器的搭建及详解
- c++ 使用socket实现C/S端文件的下载传输
- java异常
- php核心函数xdebug_debug_zval
- Struts框架入门知识设置默认上传大小及编写自己的的拦截器及其配置
- FragmentPagerAdapter 和 FragmentStatePagerAdapter 区别
- C# 代码转换到Python
- php Thinkphp 3.1配置文件相应总结
- Eclipse环境安装C/C++插件CDT和Eclipse安装的插件卸载(删除)
- STL中的map、unordered_map、hash_map
- java HSSFCell 导入获取时间,通过时间戳转换时间
- java四舍五入与截取
- Qt 延时
- 关于Matlab中句柄@的用法
- PHP IDE PHPStorm配置支持友好Laravel代码提示方法
- php中简单的邮箱匹配
- C# 5.0 与 .Net 4.5 学习(二)Deadlocks死锁
- ftp上传下载文件
- php下载文件
- 线程实例代码