ZhgChg.Li

XCodeアップグレードで必須チェック|Releaseビルドの幽霊クラッシュ対策とロジック確認

Releaseビルド時のみ発生する幽霊クラッシュやロジック問題に悩む開発者向けに、XCodeアップグレード時の効果的な検証手法を解説。Debugでは見えない不具合を早期発見し、安定したリリースを実現します。

XCodeアップグレードで必須チェック|Releaseビルドの幽霊クラッシュ対策とロジック確認
本記事は AI による翻訳です。お気づきの点があればお知らせください。

[通霊ノート] XCode アップデート時に必ずテストすべきこと…

Build Configuration Release(リリース版、オンライン版)でのみ発生する原因不明のクラッシュやプログラムの論理問題に遭遇したが、Debugでは問題なく動作する。

Photo by Tommaso Pecchioli

Photo by Tommaso Pecchioli

TL;DR

新しい XCode でプロジェクトをビルド・リリースする前に、単に Build & Run でレイアウト崩れや異常がないか確認するだけでなく、以下もぜひ試してみてください

  1. App ターゲットを選択する

  2. Build Settings を選択する

  3. Optimization Level を検索する

  4. Optimization Level セクションを見つける

  5. Debug 環境も Release と同じ値に設定する(例:Fastest, Smallest [-Os]

  6. ビルドして実行し、異常がないか確認する

Testflight に直接アップロードしてテストしないのは、問題が発生した際にすぐにブレークポイントで原因を特定できるようにするためです。

もしユーザーからRelease(正式版、オンライン版)での問題(クラッシュや動作異常)が報告され、開発者がローカルで再現できない場合は、この設定を変更してローカルで試してみてください。

発生する可能性のある問題

  • コード上は正しいが、結果が異常になる

  • コード上はクラッシュしないはずの箇所でクラッシュする

上記は Debug 環境の Optimization Level = None [-O0] では正常に動作し、Optimization Level = Fastest, Smallest [-Os]、つまり Release の設定値でのみ発生します。

解決策

問題がある場合、多くは開発者のせいではありません;XCode の最適化バグが原因です。このバージョンの XCode でどうしてもビルドする必要がある場合は、自分でプログラムのワークアラウンドを調整し、新しいバージョンの XCode が出るのを待って正常かどうか確認してください。

Release を直接 None に変更することは推奨しません。なぜなら、他の問題がさらに発生する可能性があるためです。

お話の時間

以下はここ数年の仕事で実際に遭遇した問題の事例です。

ストーリー 1 — アプリが評価依頼のポップアップを繰り返し表示する問題

私たちのアプリには以前、「アプリを開くとユーザーにアプリストアで評価をお願いする」機能がありました。ルールとしては3回表示したらそれ以上は表示しないようにしていました。しかし、多くのユーザーから毎回アプリを開くたびに表示され続けると報告があり、長期間ずっと何度も表示されてうるさいと不満が出ていました。

しかし、コードを見てもローカルでビルド&実行し、シミュレーターや実機で試しても問題はありません。さまざまなエッジケースのシナリオも試しましたが再現できませんでした。UIテストを作成して何千回もパスを繰り返し、データをクリアして再試行しても問題は発生しませんでした。

あの時は夜中の3時過ぎまで悩み抜き、もうどうしようもなくて原因が全く思いつかず、目的もなくプロジェクト設定を見ていたら、ふと「Build SettingsをすべてReleaseの値に変えてみよう」と思いつきました。そこで初めて「Optimization Level = Fastest, Smallest [-Os]」で再現することがわかり、問題の箇所を特定できました。

擬似コード

var invitedTimes = 0 // UserDefaultsから読み込み;更新後に再保存される
func requestAppStoreReviewIfNeeded() {
  defer {
    invitedTimes += 1 // 今のところ動作するが、予期しない副作用があるかもしれない
  }

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

このコードは前任者が開発したもので、コードを見る限り副作用はあるものの、ロジックに問題はなく、正常にコンパイルでき、実行も以前のバージョンでは問題ありませんでした。

しかし、Optimization Level = Fastest, Smallest [-Os] に設定してブレークポイントで値をプリントすると異常が見つかりました。invitedTimes += 1 の後、値が突然 -24760045646797946 のような非常に大きな負の数に変わってしまい、そのためユーザーは毎回招待評価が表示されてしまいます。

当時はまずこの defer の書き方を直接変更し、それ以降は同様の問題のユーザー報告はありませんでした;その後、後続の XCode バージョンで同じ書き方と Optimization Level = Fastest, Smallest [-Os] でも正常に動作することを確認しました。

ストーリー 2 — あるページで直接クラッシュする

Release (Testflight) 版の内測で、あるページ(WebView)をクリックすると必ずクラッシュする問題が発見されました。しかし、エンジニアがシミュレーターや実機で Build & Run しても問題は発生しません。問題の原因を推測しては、ログを埋め込んだり修正したバージョンを Testflight にアップロードしてテストするという作業を繰り返し、とても時間がかかりました。その時、以前の恐怖がよみがえり、すぐに同僚にローカルの設定を Optimization Level = Fastest, Smallest [-Os] に変更してもらい、Build & Run したところ、見事にローカルでクラッシュ問題を再現できました。

主な問題は、私たちが独自に特化した WebView の Obj-c コード内の変数が、Optimization Level = Fastest, Smallest [-Os] のときに null になることで、原因は不明です。とりあえずチェックを増やして保護しています。以前のバージョンでは正常だったため、新しい XCode がリリースされるのを待って、正常になるか試すしかありません。

まとめ

実はこの罠に二度もはまっただけでなく、覚えていないものもあります。とにかく心得を残しておきます:

  1. 新しい XCode バージョンで初めてリリースビルドを行う際は、必ずこれをテストしてください。

  2. 問題は Release(正式版、オンライン版)でのみ発生します。基本的にこの問題について、設定を変更してローカルで再現できるか確認してください。

Post は Medium から ZMediumToMarkdown によって変換されました。

GitHub で編集
この記事を改善
本記事は Medium で初公開
オリジナルを読む
この記事をシェア
リンクをコピー · SNS でシェア
ZhgChgLi
著者

ZhgChgLi

An iOS, web, and automation developer from Taiwan 🇹🇼 who also loves sharing, traveling, and writing.

コメント