之前看过一篇文章(具体的找不到了),讲的是项目中引用的某个第三方库使用了MethodSwizzle,导致的bug死活查不出来。若不是那个第三方库是自己公司开发的,能够看到源代码,不然这个bug可就成了无头冤案了。

其实还有一类东西,和第三方库很类似,一旦出了bug,那可真是生不如死,那就是Tweak。

Tweak俗称越狱插件,之前写了文章介绍过,具体可以看这里。它的特点在于:

  1. 是一个动态链接库
  2. 依赖于越狱工具MobielSubstrate,能够动态替换扩展iOS 上系统方法,作用和MethodSwizzle类似
  3. 可以指定注入特定的进程。说白了,它是被注入的应用程序的一部分

和第三方库类似,一旦出了问题,会直接连累宿主程序,具体原因参见上面第三点。比方说,某Tweak里,MethodSwizzle了某个系统函数,乱搞一通甚至不回调原有的实现,这种bug靠平常的解决手段,是很难发现解决的;或者说,某Tweak出现了setObject:forKey:的空object值崩溃(不要笑,真见过这种低级错误),会直接挂了你的程序。

曾经参与过某浏览器的开发,对崩溃率把关及其严格。从上报的崩溃日志可知,第三方Tweak导致的崩溃,实际上已经占到崩溃比率很大的一部分。特别是某狗输入法,某数字公司和某国宝桌面的Tweak,由于用户量极大,收集到的崩溃日志极为可观。虽说和人家交涉,人家确认在新的版本已经修复,但由于Cydia和Appstore不同,用户其实是很少升级第三方Tweak的,结果就是,崩溃率就摆在那里不高不低,打碎牙齿自己咽下去吧。

另外第三方Tweak还可能出现另外一种情况,那就是,双方同时引用了某个第三方库——如著名的Reachability,冲突了。由于Tweak是以动态链接库的形式注入的,宿主程序运行毫无压力,但由此引发的异常表现,却是始料不及的。

比方说,同事有过这样的经历:自己写的函数,断点死活就是进不去,程序单步运行的话,直接就跳过了那个函数,那个函数就和不存在一样,而且,这个问题只在一部手机上面出现!

通过image lookup 查看符号表如下图,结果就很明显了:

第三方Tweak AutoTouchTweak声明了一个UIImage的扩展函数,正好和自己程序的函数一模一样。

解决方法可以有:

  • 不越狱(但你没法说服你的用户都不越狱)
  • 通知第三方Tweak的作者修改(呵呵有的都已经几年没更新了)
  • 在某些工具类或工具函数,加上自己程序特有的前缀(靠人不如靠己)

最后,我想说的是,我一直都很崇拜那些开发第三方类库的作者,当然只是那些适用性和稳定性都很高的第三方类库的作者。