Post

XCode 升级必测:Build Settings 优化等级调整快速定位 Release 版幽灵闪退问题|iOS 开发实战技巧

iOS 开发者遇到 Release 版才出现的闪退或逻辑异常,借由将 Debug 优化等级调整与 Release 同步,快速在本地复现问题,节省测试时间并精准定位 XCode 优化造成的 Bug,提升发布稳定度与维护效率。

XCode 升级必测:Build Settings 优化等级调整快速定位 Release 版幽灵闪退问题|iOS 开发实战技巧

Click here to view the English version of this article.

點擊這裡查看本文章正體中文版本。

基于 SEO 考量,本文标题与描述经 AI 调整,原始版本请参考内文。


[通灵笔记] XCode 升级时最好测一下的事…

遇到仅在 Build Configuration Release (正式版、线上版)才会出现的幽灵闪退或程式逻辑问题,但是 Debug 安然无恙。

Photo by [Tommaso Pecchioli](https://unsplash.com/@pecchio?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash){:target="_blank"}

Photo by Tommaso Pecchioli

TL;DR

使用新 XCode 打包发布专案之前,除了直接 Build & Run 玩玩看有没有跑版或异常, 请记得也试试看

  1. App Target

  2. 选择 Build Settings

  3. 搜寻 Optimization Level

  4. 找到 Optimization Level 区块

  5. Debug 环境也设定同 Release 的值 (e.g. Fastest, Smallest [-Os] )

  6. Build & Run 测看看有没有异常

不选择直接打包上 Testflight 测试是为了方便我们遇到问题的时候,能即时用断点找到问题根源。

如果遇到使用者在 Release (正式版、线上版) 回报的问题(闪退或行为异常),但开发者无法在本地复现,也可以试试改这个设定在本地试试看。

可能出现的问题

  • 程式上看正确,但结果异常

  • 程式上看不会闪退的地方,却会闪退

以上在 Debug 环境 Optimization Level = None [-O0] 都是正常的,只会出现在 Optimization Level = Fastest, Smallest [-Os] 也就是 Release 的设定值。

解法

有问题的话,问题多半跟开发者无关 ;是 XCode 优化的 Bug 导致,若一定要用这版 XCode 打包那只能先自己调整程式 Workaround,等待新版 XCode 出来再测看看是否正常。

不建议直接把 Release 改成 None,因为可能会有更多其他问题。

说故事时间

以下是这几年工作中实际被这坑坑过的问题场景。

故事 1 — App 一直跳邀请评价 App Popup

我们的 App 之前有一个功能是打开 App 时会「邀请使用者去应用商城给评价」规则是跳三次之后就不会在跳;但是收到很多使用者回报每次开 App 都会跳,持续很久了,一直问一直问很烦。

但是我们从 Code 上看跟在本地 Build & Run 在模拟器或实机上都没问题,也试过各种 edge case 场景都无法复现;我甚至撰写了一个 UI Test 疯狂重跑路径、清除资料重试…跑了几千次都没遇到问题。

记得那次我苦恼到半夜三点多,万念俱灰实在想不到是什么问题,开始漫无目的的查看专案设定,突然灵机一动想说那把 Build Settings 都改成 Release 的值试试看好了,这才发现问题在 Optimization Level = Fastest, Smallest [-Os] 能重现,也因此才定位到出问题的位置。

Pseudocode

1
2
3
4
5
6
7
8
9
10
11
12
var invitedTimes = 0 //  Loaded from UserDefaults; will be saved back after update
func requestAppStoreReviewIfNeeded() {
  defer {
    invitedTimes += 1 // Works for now, but may have unintended side effects
  }

  guard invitedTimes < 3 else {
    return
  }
  
  self.present(AppStoreReviewRequestAlert())
}

这段程式是前人开发的,从程式上看这段程式码虽然有 side effect,可是逻辑无问题、可以正常 Compile、在执行上之前的版本也都没有问题。

但当我把 Optimization Level = Fastest, Smallest [-Os] 之后下断点 Print 值就发现异常了, invitedTimes += 1 之后会直接爆炸变成 -24760045646797946 一个极大的负数,也因此使用者每次都会跳邀请评价。

当时先直接改掉这边 defer 的写法,就再也没有使用者回报类似的问题了;后来回头测试后续的 XCode 版本,相同的写法、 Optimization Level = Fastest, Smallest [-Os] 也能正常运作了。

故事 2 — 某个页面会直接闪退

Release (Testflight) 版在内测的时候发现有一个页面(WebView) 只要一点击就会闪退,可是工程师怎么 Build & Run 在模拟器或实机上都没问题;每每猜测一个问题点就打包一个埋 Log 或是尝试修正的版本上 Testflight 测试,非常痛苦费时;这时又唤起我上次被支配的恐惧,立刻请同事把本地的设定改成 Optimization Level = Fastest, Smallest [-Os] 然后在 Build & Run 果然在本地复现了闪退的问题点。

主要问题是出在我们自己特化的 WebView Obj-c Code 中有一个变数在 ptimization Level = Fastest, Smallest [-Os] 时会变 null,原因不明,只能先多加判断保护;在之前版本也都正常,只能等新的 XCode 推出后再试试看是否正常。

总结

其实不只被这个坑坑了两次,有些已经不记得了,总之就是留个心法:

  1. 使用新 XCode 版本第一次打包上版时,最好测一下这个

  2. 问题只发生在 Release (正式版、线上版),基本上就是这个问题,可以直接改设定在本地看能不能复现

有任何问题及指教欢迎 与我联络


Buy me a beer

本文首次发表于 Medium (点击查看原始版本),由 ZMediumToMarkdown 提供自动转换与同步技术。

Improve this page on Github.

This post is licensed under CC BY 4.0 by the author.