【詰んだ】iOS Firebaseのイベントが送信されず2週間苦しんだ話
Table of Contents
※ 正しく導入したのにDebugViewにイベントが表示されない方は「FirebaseのDebugViewが表示されなかったときの対応」をご参照ください。
モバイルアプリ向けGoogle Analyticsが、2019年10月末で終了するため、アナリティクス機能をFirebaseへ移行しています。 移行自体は難しい作業ではないはずですが、イベントがなかなか送信されず、僕は2週間もスタックしてしまいました。 原因は、Cocoapodsの設定の仕方でした。今回は、その原因と対策について、まとめておきたいと思います。
症状 #
Google AnalyticsからFirebaseのアナリティクスへ移行するため、Cocoapodsを使用してFirebase/Analytics
への依存を追加しました。しかし、自動計測以外のイベント、すなわち自分で追加したアナリティクスのイベントやユーザープロパティのセットなどの処理が、まったく送信されませんでした。
前提 #
- FirebaseはAppDelegate内で、正しく
FirebaseApp.configure()
されている - 環境ごとの
GoogleService-Info.plist
を用意しているが、それらも正しくconfigureメソッドでセットされている - 自動で送信されるイベントは、ちゃんと送信される
- 手動で送信したいイベントは、なぜか送信されない
setScreenName
logEvent
setUserID
setUserProperty
viewDidAppear
で実行するsetScreenName
は、なぜか送信されるが、それ以降は全く動作しない
このように、自動で送信されるイベント + viewDidAppear
でsetScreenName
したイベント以降は、まったく送信されませんでした。
原因判明のきっかけとなったログ #
以下のようなログが出ていないか、チェックします。
objc[25445]: Class FIRAnalytics is implemented in both [library path in target “A”] and [library path in target “B”]. One of the two will be used. Which one is undefined.
つまり、FirebaseがターゲットAのものか、ターゲットBのものか、明確にされていませんというログでした。 なぜ?Firebaseはひとつなのでは……?
複数のtargetのあるプロジェクト #
アプリのアーキテクチャ、依存関係に問題がありました。
プロジェクトは、プレゼンテーションレイヤーとモデルレイヤーを分けるため、マルチモジュールの構成 = 複数のターゲットで構成していました。ここでは、アプリとモデルとします。アプリは、モデルに依存しています。さっき見たログは、どちらのターゲットもFirebaseに依存しているために出力されたログでした。
このとき、アプリ内のソースコードで import Firebase
を書くと、どのターゲットのFirebaseか判別することができないというわけです。
解決: Cocoapodsの設定 Podfileを修正 #
こうなった原因は、Podfileの書き方が、複数のターゲットに対して包括的に依存を解決させるようなものになっていたためでした。 ちょうど、Qiitaの記事(Embedded Framework使いこなし術)にあるコメントにあるような設定になっていました。
こんなイメージ。
abstract_target 'MyApp' do
platform :ios, '8.0'
use_frameworks!
pod 'Firebase/Analytics'
target 'Application' do
# Firebaseが必要なターゲット
end
target 'Model' do
# 本来、Firebaseが不要のターゲットなのに依存している
end
end
そこで、Firebaseが必要なターゲットだけFirebaseに依存するように、書き方を変更しました。
abstract_target 'MyApp' do
platform :ios, '8.0'
use_frameworks!
# pod 'Firebase/Analytics' ← こちらは削除
target 'Application' do
# Firebaseが必要なターゲット
pod 'Firebase/Analytics' # ここに追加
end
target 'Model' do
# 本来、Firebaseが不要のターゲットなのに依存している
end
end
こうすることで、モデルからFirebaseへの依存がなくなり、FirebaseのAnalyticsが正しく動作するようになりました。
より良いソリューション #
ターゲットの依存関係に即してCocoapodsの依存を書いていくのがより理想的なんだと思います。 こちらの記事(CocoaPodsでFirebaseをmain target以外に入れることができない問題(解決済))が参考になります。
まとめ #
Firebase向けGoogle Analyticsへ移行していた際に、2週間もスタックしてしまった現象の原因について書きました。 マルチモジュール構成のプロジェクトで、Cocoapodsを使うときは、重複して依存しないように注意しなけれいけないとわかりました。 そして、2週間、まったく見落としていたログに原因があったことから、多くの学びがありました。
- 問題となっている機能周辺のログは注意深く見ること
- それでもスタックしたらログを俯瞰し、問題となっている機能以外のログにも目を通すこと
先入観なくログを見ないといけないなと痛感しました。