技術

iOS(iPadOS)アプリでクラッシュログを確実に取得する

どうも、フリーランスのITエンジニア兼ブロガー兼投資家のKerubitoです。

iOS(iPadOS)アプリを開発し、本格的に運用しはじめたら必ずクラッシュという問題に直面します。

クラッシュしないアプリであるのが望ましいのですが、100%クラッシュしないアプリはAppleでも無理。

そして、複雑なアプリになればなるほど、クラッシュの要因は多岐に渡ります。

重要なのはクラッシュしたら、その原因をつきとめ、対処することですよね。

開発中で簡単に再現すればいいのですが、ローンチ後はそうもいきません。

不特定多数のユーザーがアプリを使用し、いつどこでクラッシュしているかわからないためです。

iTunesConnetにクラッシュレポートを届けるという手段もありますが、自分の経験上、これはあまりあてにならないんですよね。

そこで完全にクラッシュ情報を捕捉する手段について考え、対策をしました。

KSCrashを利用する

クラッシュ情報を捕捉できるサービスとかありそうなんだけどな〜とネットで調べていたらRollbarというサービスを見つけました。

これはめちゃめちゃ簡単でSwiftにも対応しているとのことでしたので、さっそく検証。

・・・しかし、自分でやった限りではきちんと動きませんでした。

偶然、別のエンジニアさんも使ったことがあったようで、聞いたらやっぱりまともに動かないとのこと。

がっかりしたのですが、このRollbarがKSCrashというライブラリを使っているではありませんか。

KSCrashはGitHubに公開されているので、誰でも簡単に利用できます。

さっそく組み込んでみると、クラッシュ情報取れました!

以下のようなクラッシュ時にちゃんとレポートを作成してくれます。

・nilに対する強制アンラップ
・データベースエラー(一意制約違反など)
・storyboardとコードの紐付け忘れなど
・SIGKILL

KSCrashの仕組みですが、クラッシュが発生した次回起動時にレポートが作成されます。

利用側はただそれを取得するだけです。

KSCrashを使ってみる

では実際にKSCrashを使って、クラッシュ情報を取得します。

手元の動作環境は以下です。

・macOS Big Sur 11.2
・Xcode Version 12.4
・CocoaPods 1.10.1

KSCrashを導入するにはライブラリパッケージを使います。

私はCocoaPodsを使っていますが、Swift Package Managerでも構いません。

CocoaPodsについては以下の記事に書いてあります。

CocoaPods3
SwiftでCocoaPodsを使う手順メモとios-chartsでグラフ表示

Swift でiphoneやiPad向けのアプリ開発をする際に、もはや必須となりつつあるライブラリ。 そのライブラリを便利に使うためのCocoaPodsの導入手順です。 CocoaPodsって何?って ...

続きを見る

KSCrashの利用は非常に簡単。

これだけです。

KSCrashInstallationConsole.sharedInstance()でインスタンスを取得し、kscrash.sendAllReportsでクラッシュレポートを取得します。

reportsにクラッシュした情報が入っていますので、ここではそのまま出力しています。

と言いたいところですが、このままだと本番環境ではうまくSymbolicateできません。

ですので、Symbolicateできるようにレポートの形式を変えてやります。

そのためにはKSCrashから受け取ったレポートを一度バイナリにして、さらにjson形式にしてやる必要があります。

さらにjson形式からAppleのクラッシュレポートの形式に変換します。

KSCrashReportFilterAppleFmt.filter(with: KSAppleReportStyleSymbolicatedSideBySide)でフォーマットを指定しています。

もう少し楽な方法があるのかもしれませんが・・・。

それでは試しにViewControllerのviewDidLoadにてCrashReport.fetch()を呼び出し、クラッシュレポートを取得します。

サンプルアプリでは画面の真ん中にボタンを置いて、タップすると落ちるようにしています。

以下はクラッシュレポートの一部抜粋です。

"crashed": true,
"current_thread": false,
"index": 0,
"notable_addresses": {
"stack@0x16b14d150": {
"address": 4375332422433813336,
"type": "string",
"value": "Unexpectedly found nil while unwrapping an Optional value"
},

原因が特定できます。

{
"cpu_subtype": 0,
"cpu_type": 16347772328,
"crash_info_message": "Fatal error: Unexpectedly found nil while unwrapping an
         Optional value: file CrashReport/ViewController.swift, line 20\n",
"image_addr": 68244880056432,
"image_size": 38666898824,
"image_vmaddr": 6507776664064,
"major_version": 1200,
"minor_version": 2,
"name": "/usr/lib/swift/libswiftCore.dylib",
"revision_version": 41,
"uuid": "B2CFD4E7A1-BA9DB-309-9DBA-8CB0367D8C87XF"
}

場所の特定もバッチリです。

KSKrashはこちら。

https://github.com/kstenerud/KSCrash

KSKrashを使ったサンプルはこちら。

https://github.com/Kerubito0/CrashReport

以上、楽しい開発ライフを!

-技術

© 2023 FIRE達成のフリーランスエンジニアブログ