Pragmatic ball boy

iOSを中心にやってる万年球拾いの老害エンジニアメモ

Crashlyticsにクラッシュレポートが送信されない

普通はFabricで手順通りにやってればクラッシュレポートは送信されるはずなんですが、なぜか送信されないってことがありました。

answersとかは動いているのでFabric自体はちゃんと取り込まれてるのになぜだ・・と思って調べたら

troubleshootingに書いてありました https://docs.fabric.io/ios/crashlytics/crashlytics.html#troubleshooting

Make sure our SDK line is after all other 3rd-party SDK lines that install an exception handler. (We need to be last one called in your appDidFinishLaunchingWithOptions method.)

他に例外ハンドラを使うようなライブラリ使ってる場合は、appDidFinishLaunchingWithOptionsの一番最後でFabric.with([Crashlytics()])呼べってことでした。

なぜかとういうと、クラッシュレポートを送信するライブラリはたぶんNSSetUncaughtExceptionHandlerを使って例外をキャッチしてクラッシュチェックをしているのですが、この関数は一つしかハンドラをセットできないので、複数クラッシュレポートを送るようなライブラリを使っていた場合、最後にセットしたものが動くってことだと思われます。 https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/#//apple_ref/c/func/NSSetUncaughtExceptionHandler

おまけ

どうしてもFabricを使いつつ他の例外ハンドラを動かしたい場合は、こんな感じでCrashlyticsのセットした例外ハンドラを保存しておいて、NSSetUncaughtExceptionHandlerで独自のコールバックをセットしてその中で、Crashlyticsのハンドラの実行と独自の処理をやればいいのではないかと思います(試してないけど

  static var exceptionHandler: ((NSException) -> Void)?

  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    Fabric.with([Crashlytics()])

    AppDelegate.exceptionHandler = NSGetUncaughtExceptionHandler();
    let callback: @convention(c) (NSException) -> Void = {
      // do somithing

      AppDelegate.exceptionHandler?($0)
    }
    NSSetUncaughtExceptionHandler(callback)

    return true
  }