はじめに
クラッシュが原因でAppleからリジェクトを食らうと、ご丁寧にクラッシュログを添付してくれることがあります。
しかしそれを見ただけでは実際どこでクラッシュしたのか分かりません。そんなときに必要となるのが「ログの解析」です。
今回は備忘録として、解析の手順から結果の読み解き方までを記しておきたいと思います。
手順
下準備
まずはAppleから送られてきたクラッシュログをclash_log.txt
とかでデスクトップに保存します。
あと審査に提出したArchiveの.dSYMファイルも必要なので、下記の手順で同様にデスクトップ保存します。
- Xcodeを起動する
- Window > Organizerを選択
- アプリ申請時に指定したArchiveを右クリック > Show in Finderを選択
- 対象の.xcarchiveファイルを右クリック > パッケージの内容を表示を選択
- dSYMsディレクトリの中にアプリ名.app.dSYMファイルがあるのでデスクトップにコピーする
解析する
ファイルを保存したデスクトップに移動します。
cd ~/Desktop
このあとのコマンドでエラーが出ないようにするおまじないをかけます。
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer/
最後に解析結果を書き出します。
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash -v ~/Desktop/clash_log.txt ~/Desktop/アプリ名.app.dSYM > crash.txt
うまくいくとターミナルに結果がぶわっと吐き出されて、ファイル(crash.txt)が書き出されます。
ファイルの中身をエディタで見てみると、解析されたっぽいログが並んでいるのが確認できると思います。(空のファイルができてしまった場合、残念ながら失敗です)
解析結果を読み解く
結果が出たのはいいものの、ざっと1000行近くのログが並んでおり、「これどうやって見たらいいんだ…」と途方に暮れたくなるかもしれません(わかります、私もそうでした)。
とりあえず上の方から見ていきましょう。
app_name:
Date/Time:
OS Version:
よく見知った単語が並んでおり少し安心できます。はじめの20行ほどはログの基本情報だと見て取れました。
その先に出てくるのがクラッシュした原因です。
Exception Type: EXC_BREAKPOINT (SIGTRAP)
今回のEXC_BREAKPOINT
というのは、Appleのドキュメントによると
・使用しようとしたオプショナル型がnilだった
・型変換に失敗した
といった原因が考えられるようです。
じゃあそれが具体的にどこで起きているのか。それがその先にずらーっと並んでいるスタックトレースに記されています。
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 HogeApp 0x0000000104844dd4 specialized Fuga.init(json:) + 904660 (Fuga.swift:355)
1 HogeApp 0x0000000104844a84 specializedFuga.init(json:) + 903812 (Fuga.swift:355)
2 HogeApp 0x000000010483dee4 Fuga.init(json:) + 876260 (:0)
・・・
「え、このトレース全部読まないといけないの…?」と絶望感に苛まれる方もいるかもしれません(わかります、私もそうでした)。
スタックトレースは例外の発生状況と発生個所を示すもので、プログラムを実行した情報を「下から上に」積み上げていきます。
つまり一番上(とその周辺)に書かれた行のクラス・行数を見ることで、実際にどこでクラッシュしたのかを読み取ることができるのです。全ての行に目を通す必要はありません。
Thread 0
というのはメインスレッドのことなので、
上の例だとメインスレッドの、Fugaクラス355行目で、オプショナル型がnilだったり型変換に失敗したりしたというような理由でクラッシュしたのだ!と突き止めることができると思います。
これで無事にバグを修正し、再申請に持っていくことができそうですね
さいごに
一度手順を覚えてしまえばどうってことのないクラッシュログ解析ですが、初めて自分でやろうとすると結構骨が折れました。「解析」という難しそうな言葉に尻込みしてしまう方もいるかもしれません。そんなときこの記事が少しでもお役に立てば嬉しく思います。
以下に参考にさせていただいた記事を載せておくので、さらに詳しく知りたいという方は合わせてどうぞ。
iOSのクラッシュログをSymbolicate(復元)して解析する - Qiita
iOSアプリのクラッシュログを解析する - 備忘録
スタックトレースからデバッグのヒントを読み取る:デバッグのヒント教えます(2) - @IT
Javaのエラー解決の王道~スタックトレースの読み方~ | ITのおもちゃ箱
iOS - appleからのクラッシュ報告でリジェクトをくらい、クラッシュログの解決が出来ない。|teratail