今天有同事遇到问题,他重写viewDidAppear:方法,但是,代码并没有执行到。后来我发现,是另个一同事用了黑魔法搞的鬼,而且他本人并不知道这么做会产生影响。(本文中所有黑魔法指Swizzle)

我展示下hook的代码

[self aspect_hookSelector:@selector(viewDidAppear:) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> info, BOOL animated) {

UIViewController *vc = [info instance];

[vc AspectBeforeViewDidAppear:animated];

} error:&error];

error = nil;

[self aspect_hookSelector:@selector(viewDidAppear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> info, BOOL animated) {

UIViewController *vc = [info instance];

[vc AspectAfterViewDidAppear:animated];

} error:&error];

作者的原意是想在viewDidAppear:执行过程中,在前面执行一些代码,在后面也执行一些代码。魔法的可怕之处来了:难以操控。

明白了需求,看看到底问题出在了哪里

先做如下指代原函数viewDidAppear:为SEL1,其实现IMP1

原函数执行后的函数SEL3——>IMP3(SEL3)

他设想的两次hook方法实际执行如下。
第一次hook后,
原函数SEL1———>IMP2(SEL2)
原函数执行前的函数SEL2——>IMP1
原函数执行后的函数SEL3——>IMP3(SEL3),
第二次hook,
原函数SEL1———>IMP3(SEL3)
原函数执行前的函数SEL2——>IMP1
原函数执行后的函数SEL3——>IMP2(SEL2),
 
所以最后执行的顺序是调用SEL1寻找到IMP3,执行IMP3的过程中,由于IMP3中会调用SEL3,也就是执行IMP2(如果不明白,请查看swizzle的实现)。原函数的理应被SEL3中调用指向IMP1(SEL2)调用到,但是aspects存在bug,导致IMP2中的SEL2丢失,导致原函数被跳过。aspects的相对而言调用了很多底层函数,合运行时,大部分开发者很难读懂,除了问题也难也解决。
 
最后提出忠告,这种形式的AOP最好只处理简单而统一的业务,这种情况下,的确可能让代码清晰,抽离不想干的逻辑。函数换来换去却是挺绕的,除非你真的知道自己在做什么,否则还是换条路,不然也不好维护,同事可能会出现莫名其妙被捅了一刀的感觉。文笔不太好,再补充点,AOP很容易导致入侵性的代码,最好不要去hook的方法里不要增加对系统sdk属性的操作,你可以自己增加一些属性来操作。以不影响别人的代码

iOS开发中乱用hook可能导致灾难的更多相关文章

  1. iOS开发中静态库之".framework静态库"的制作及使用篇

    iOS开发中静态库之".framework静态库"的制作及使用篇 .framework静态库支持OC和swift .a静态库如何制作可参照上一篇: iOS开发中静态库之" ...

  2. ios 开发中 动态库 与静态库的区别

    使用静态库的好处 1,模块化,分工合作 2,避免少量改动经常导致大量的重复编译连接 3,也可以重用,注意不是共享使用 动态库使用有如下好处: 1使用动态库,可以将最终可执行文件体积缩小 2使用动态库, ...

  3. GIT在iOS开发中的使用

    前言 在iOS开发中,很多公司对项目的版本控制管理都使用了git,当然也有部分公司使用的是svn.当年我最初接触的是svn,觉得使用起来挺方便的,但是每次切分支都需要下载一份新的代码起来,这实在太麻烦 ...

  4. IOS开发中UI编写方式——code vs. xib vs.StoryBoard

    最近接触了几个刚入门的iOS学习者,他们之中存在一个普遍和困惑和疑问,就是应该如何制作UI界面.iOS应用是非常重视用户体验的,可以说绝大多数的应用成功与否与交互设计以及UI是否漂亮易用有着非常大的关 ...

  5. iOS开发中的4种数据持久化方式【一、属性列表与归档解档】

    iOS中的永久存储,也就是在关机重新启动设备,或者关闭应用时,不会丢失数据.在实际开发应用时,往往需要持久存储数据的,这样用户才能在对应用进行操作后,再次启动能看到自己更改的结果与痕迹.ios开发中, ...

  6. 解析iOS开发中的FirstResponder第一响应对象

    1. UIResonder 对于C#里所有的控件(例如TextBox),都继承于Control类.而Control类的继承关系如下: 代码如下: System.Object System.Marsha ...

  7. 在iOS开发中,给项目添加新的.framework

    首先需要了解一下iOS中静态库和动态库.framework的概念 静态库与动态库的区别 首先来看什么是库,库(Library)说白了就是一段编译好的二进制代码,加上头文件就可以供别人使用. 什么时候我 ...

  8. iOS开发中你是否遇到这些经验问题

    前言 小伙伴们在开发中难免会遇到问题, 你是如何解决问题的?不妨也分享给大家!如果此文章其中的任何一条问题对大家有帮助,那么它的存在是有意义的! 反正不管怎样遇到问题就要去解决问题, 在解决问题的同时 ...

  9. 深入理解 iOS 开发中的锁

    来源:伯乐在线 - 夏天然后 链接:http://ios.jobbole.com/89474/ 点击 → 申请加入伯乐在线专栏作者 摘要 本文的目的不是介绍 iOS 中各种锁如何使用,一方面笔者没有大 ...

随机推荐

  1. PMD(Put Me Down)用例测试

    PMD(Put Me Down)--用例测试 一.测试工作安排 6个成员随机分配一个模块进行测试,测试完成后将最后的结果汇总到测试用例文档中. 二.测试工具的选择与运用 测试工具选择:这次还没用工具, ...

  2. 一起买beta版模块单元测试

    一起买beta版模块接口单元测试 测试目的 保证代码质量,对各个模块进行单元测试,不仅可以有效地保证代码的可靠性,让模块在与别的模块整合时出现更少的错误. 而且不用每次启动程序而等待浪费时间. 单元描 ...

  3. POJ3208:Apocalypse Someday

    传送门 很神奇的一道题,正解是AC自动机+数位DP,个人感觉POPOQQQ大爷的方法更方便理解. 按照一般套路,先搞个DP预处理,设$f[i][0/1/2/3]$分别表示对于$i$位数,其中有多少个前 ...

  4. JavaScript事件类型

    JavaScript事件类型 Web浏览器中可能发生的事件有很多类型.这里我将主要将下面几种常用的事件类型: UI事件 焦点事件 鼠标与滚轮事件 键盘与文本事件 复合事件 变动事件 HTML5事件 设 ...

  5. javascript应用之如何判断一个数为素数

    判断是否为素数? 质数(prime number)又称素数,有无限个.质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数的数称为质数. 合数,数学用语,英文名为Composite numb ...

  6. ionic 发送请求返回一直都是404

    在web端调试一直都没有问题,生成app之后发现所有的请求返回的都是404, 断掉wifi和4G之后发送的也是404 原因是未引入插件 解决方法是在根目录下执行一下命令 cordova plugin ...

  7. C#最简单最完整的webservice实例

    http://fyinthesky.blog.163.com/blog/static/3555251720110115227337/ 我做java,但最近接触crm所以必须研究一下C#中的webser ...

  8. JavaScript学习笔记——DOM_document对象

    javascript-document对象详解 DOM document(html xml) object modledocument对象(DOM核心对象) 作用: 1.内容 innerHTML 2. ...

  9. hdu 1873 看病要排队(优先级队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1873 题目大意: 三个医生看病,病人排队看病,病人有优先级,优先级高的提前看病,同样的优先级按先后.I ...

  10. C# Language Specification

    https://msdn.microsoft.com/en-us/library/aa645596(v=vs.71).aspx