今天 App 遇到了一个奇怪的问题,对 Swift 还没到 Production 质量才有了深刻的体会。于是决定记录一下这个问题的来龙去脉,希望不久以后回头再看这个问题的时候,Swift 已经有了很大改善。
这个问题非常简单:
在 App 使用的过程中,会有一种情况通过 Notification 的形式来弹出一个 UIAlertController,问题是,这个 Alert 的 Action 无法触发。我在 Debug 的时候却没有问题,可以正常触发。
如何去解决这个问题?
刚开始,我尝试给那段 Action 的代码打 Log,发现在 Release 模式下 Log 根本没有打出来,也就是 Action 的那块 Closure 没有被执行。然后我想了想,是不是没有在 UI 线程上做这件事情。但是我再三确认后,确实是在 UI 线程做的。我不死心,再给整个 UIAlertController 的代码强制包装了一个 GCD 的 MainQueue 操作,问题竟然解决了!
但是解决归解决,这只能是一个 Workaround,问题到底是什么引起的,我还是不知道。
后来一个朋友在微博上说,是不是 Release 版本优化级别过高造成的?
我一想,没错,Debug 模式和 Release 模式最大的不同应该就是优化级别的不同了,于是我来到项目的 Built Setings 里,对 Swift 编译器的优化级别进行了更改:
在这里,我把 Release 模式默认的优化从 Fastest [-O] 改成了 None [-Onone],然后重新编译,问题就消失了。所以问题很明显了,是 Swift 编译器的优化造成代码不灵了。具体是哪里不灵了,估计就要看汇编代码了 =。=#
想到这里,我就担心会有其他各种莫名其妙的问题,于是今天打回了 App,重新以 None 优化打包上传了一个新版本。尽管我做了简单的评测,Fastest 优化会使特定的数据处理快了10%,但是考虑到不是运算密集型的 App,我可以暂时为求稳定而放弃这不是主要的 10%。
用 Swift 这半年来(尤其这三个月用的甚为频繁),踩的坑不算多,也不算少,刚好是那种你还能忍着继续用它写下去的那种程度。
写到这里,我突然想起 Github 上的一个项目,它叫「 swift-compiler-crashes 」,我想,等到这个项目的 Crash 都解决了,我应该可以放心的启用 Swift 编译器的 Optimization 了…