【2021年版】XcodeへのCrashlyticsの設定方法

実施時期：2021月03月25日

XcodeへのCrashlyticsの設定方法について、Firebaseの公式ドキュメントのみでは分かりづらい箇所があったためこちらに記録。

まずは公式の設定方法
https://firebase.google.com/docs/crashlytics/get-started?platform=ios&authuser=1#add-sdk

特に
`${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}
`や
`$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)
`をどこに設定したら良いのか？や

どのようにするとクラッシュレポートが上がるのか？
更にいくつかエラーが出たのでその内容も。

誰かの助けとなれば幸いです。

## ステップ 1: Firebase コンソールで Crashlytics を設定する
これは分かりやすくドキュメントも多いので省略

## ステップ 2: アプリに Firebase Crashlytics を追加する
>1.Firebase プロジェクト用に作成した podfile を開き、FirebaseCrashlytics ポッドを追加します。Firebase Crashlytics でのエクスペリエンスを最適化するために、Google アナリティクス用の Firebase ポッドもアプリに追加して、プロジェクトで Google アナリティクスを有効にすることをおすすめします。クラッシュの影響を受けていないユーザーとパンくずリストをリアルタイムで取得するには、バージョン 6.3.1 以降の Google アナリティクスを追加してください。

特にイレギュラーはなかったので省略

>2.ポッドをインストールし、.xcworkspace ファイルを再度開いて Xcode でプロジェクトを表示します。
特にイレギュラーはなかったので省略

>3.Firebase モジュールを UIApplicationDelegate にインポートします。

AppDelegate.swiftの中の上部に

```AppDelegate.swift
import Firebase
```

を追記した。

>4.FirebaseApp 共有インスタンスを構成します。通常はアプリの application:didFinishLaunchingWithOptions: メソッドで行います。

AppDelegate.swiftの中で

```AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        FirebaseApp.configure()
        
        // Override point for customization after application launch.
        return true
    }
```

>5.アプリを再コンパイルします。

こちらを実施。

## ステップ 3: Crashlytics を初期化する
1,2,3,4,5を一気にまとめる。ここがどこに何を入れるかが分かりづらい。
>Xcode でプロジェクトを開き、左側のナビゲータでプロジェクト ファイルを選択します。
[Select a project or target] プルダウンから、メインのビルド ターゲットを選択します。
[Build Phases] タブを選択し、add > [New Run Script Phase] の順にクリックします。
表示される [Run Script] セクションを展開します。スクリプト フィールド（[Shell] フィールドの下）で、新しい実行スクリプトを追加します。
`${PODS_ROOT}/FirebaseCrashlytics/run`
アプリの dSYM の場所を、大規模なアプリに対する Crashlytics の自動 dSYM 生成を高速化する入力ファイルとして追加します。次に例を示します。
`${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}`
アプリのビルド済み Info.plist の場所を、ビルドフェーズの [Input Files] フィールドに指定することもできます。
`$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)`

以下具体的な方法：
Build Settingsの中の左上の+アイコンからNew Run Script Phaseを選択すると、リストの最下部にRun Scriptという項目生成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477820/5f246d90-1c8f-a173-b8ab-55148be7d6e8.png)

Shellの/bin/shの下のボックスには
`${PODS_ROOT}/FirebaseCrashlytics/run`
のみを入れ、
`${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}`
および
`$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)`
は、下の方にあるInput Filesの中に１つずつ入力する。※ここが公式の説明だとよく分からなかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477820/61de6561-e21a-5932-6303-7e27f91985b9.png)

## DWARF with dSYM Fileの設定
公式の同じページには記載がなかったが、調べるとクラッシュログを上げるためにはこの設定も必要かもしれなさそうだったので、こちらも行った。
Build Settingsの中のDebug Information Formatの中をこのようにDebug, Release共にDWARF with dSYM Fileにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477820/795ed2c1-1ffe-a3a9-bfd6-0b78bd2a714d.png)

## ビルド時のエラー
ここまでの手順を行っても、このようなエラーが出た。
>for architecture arm64 linking in object file built for iOS

~~解決策を以下に示す：
Excluded ArchitecturesのDebug、Releaseそれぞれに`arm64`を追加する~~
-> こちらを行うと実機ビルドでarchitecture周りのエラーが出たため、削除した。
削除すると実機ビルドもシミュレータービルドもうまくいったため、不要かもしれない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477820/e5d40362-cc65-e647-e8bd-34ef207896a7.png)

上記のarm64を消した後のSchemaの状態は以下の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477820/0f27615f-219d-e92a-50f4-0b5ead68d6dd.png)
この状態でシミュレーターと実機でのクラッシュ両方のデータが上がっていることが確認できた。

## その他のエラー
自分の場合は、iOSのプロジェクトファイルを入れているディレクトリまでのパスの中にGoogle Driveというようにスペースが入ってしまっている箇所があったため、そこでもNo such dir〜という旨のエラーが出た。
解決策としては単にディレクトリの名前からスペースを削除すれば良い。

以上で設定ができました。

## クラッシュさせる方法
任意の場所で以下のようにエラーを起こしてクラッシュさせる

```crash.swift
/// fatal error
fatalError()

/// NSError
let error = NSError(domain: "test error message", code: -1, userInfo: nil)
Crashlytics.crashlytics().record(error: self as! Error)

/// assert
assert(false)
```

ここで注意点としては、シミュレーターでアプリを起動させている状態だとクラッシュログが上がらないらしく、
シミュレータ上で一度アプリをスワイプして消して、再度アプリアイコンを押して単独でアプリを起動させ、クラッシュさせることでログが上がった。


以上でクラッシュのレポートが取得できるはず。
少しでも誰かの助けになればと思います。


---
Twitterの方でも仲良くしてくれる人が増えると嬉しいです！
[My Twitter Account](https://twitter.com/funny_man_daa)