Cannonball’s Journey from Fabric to Firebase

../../_images/cannonball-overview.png

From left to right: Sign In, Poem Creator, Your Poems, and About screens.

Overview

Cannonball is a magnetic poetry game. Choose your theme, get a bag of words, and start making funny stories right away!

Follow along in this guide to learn how we migrated Cannonball from Fabric to Firebase and how you can migrate your own apps.

Tip

We also migrated Cannonball for Android. It’s open sourced on GitHub. You can also read the tutorial to build Cannonball for Android.

Note

Sections marked “Bonus” are specific to Cannonball. Although they’re not necessary to migrate every app from Fabric, you can use them to learn more about Firebase!

Getting Started

Prerequisites

This guide assumes that you have a Google account and that you’re able to access the Firebase Console. It also assumes you’re familiar with Git, Xcode, and CocoaPods. Cannonball for iOS uses Swift, unfortunately there is not an Objective-C version right now.

You can follow along in Cannonball’s code by downloading its source from GitHub. If you change branches to initial, you’ll be able to see how the app looked before the migration.

Creating a Firebase project

Firebase, Crashlytics’ new home, organizes apps in a similar way to Fabric. A Firebase project is similar to a Fabric organization.

When we migrated Cannonball, we created a single Firebase project to contain both the Android and iOS versions of the app. We’d recommend you do the same for your cross-platform apps to take advantage of having shared Firebase features like Realtime Database. However, for apps that are completely different (e.g. ChatApp and CasinoApp), we’d recommend making different projects.

Transitions

Step 1. Remove the Fabric initialization code.

We’ll first need to remove Fabric from our Xcode project settings.

  1. Start by opening your app in Xcode.
  2. Remove the Crashlytics Run Script Build Phase from your Xcode project’s Build Phases.
  3. Remove your Fabric API key from your Xcode project’s Info.plist file.
  4. In your AppDelegate.swift, remove your Fabric initialization code by removing the import Fabric and import Crashlytics statements, as well as any Fabric.with() statements.

Step 2: Add Firebase to your app.

To add Firebase to your app, follow along in the Firebase documentation under “Manually add Firebase to your app”.

Here are the code changes we’ve made so far:

--- _static/diffs/AppDelegate_01.swift
+++ _static/diffs/AppDelegate_02.swift
@@ -1,6 +1,5 @@
 import UIKit
-import Fabric
-import Crashlytics
+import Firebase
 
 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -12,8 +11,8 @@
         let welcome = "Welcome to Cannonball! Please onboard with the Fabric Mac app. Check the instructions in the README file."
         assert(Bundle.main.object(forInfoDictionaryKey: "Fabric") != nil, welcome)
 
-        // Register Crashlytics, Twitter, Digits and MoPub with Fabric.
-        Fabric.with([Crashlytics.self, Twitter.self, Digits.self, MoPub.self])
+        // Use Firebase library to configure APIs
+        FirebaseApp.configure()
 
         // Check for an existing Twitter or Digits session before presenting the sign in screen.
         if Twitter.sharedInstance().sessionStore.session() == nil && Digits.sharedInstance().session() == nil {

Step 3: Set up Firebase Crashlytics.

To set up Firebase Crashlytics, follow along in the Firebase Documentation on Getting started with Firebase Crashlytics.

If your Podfile already contains pods for Fabric and Crashlytics, replace them with these version-specific pods:

pod 'Fabric', '~> 1.7.7'
pod 'Crashlytics', '~> 3.10.2'

Once you finish setting up Firebase Crashlytics, you can test your implementation by forcing a test crash in your app.

Step 4: Convert Fabric Answers to Google Analytics for Firebase.

Google Analytics for Firebase (often just called Analytics) provides the same powerful insights as Answers while integrating closely with the rest of the Firebase suite.

Analytics provides many predefined events that we recommend you use. Here’s a table of Answers events and their corresponding Analytics events:

Answers Event Analytics Event (Objective-C) Analytics Event (Swift)
logPurchaseWithPrice kFIREventEcommercePurchase AnalyticsEventEcommercePurchase
logAddToCartWithPrice kFIREventAddToCart AnalyticsEventAddToCart
logStartCheckoutWithPrice kFIREventBeginCheckout AnalyticsEventBeginCheckout
logContentViewWithName kFIREventViewItem AnalyticsEventViewItem
logSearchWithQuery kFIREventSearch AnalyticsEventSearch
logShareWithMethod kFIREventShare AnalyticsEventShare
logRating (No direct corollary) (No direct corollary)
logSignUpWithMethod kFIREventSignUp AnalyticsEventSignUp
logLoginWithMethod kFIREventLogin AnalyticsEventLogin
logInviteWithMethod (No direct corollary) Maybe: kFIREventShare (No direct corollary) Maybe: AnalyticsEventShare
logLevelStart kFIREventLevelStart AnalyticsEventLevelStart
logLevelEnd kFIREventLevelEnd AnalyticsEventLevelEnd

To migrate your Answers code to Analytics, check the getting started guide to make sure you’ve included the necessary dependencies and startup code. If you’ve already initialized Firebase in your app, you can skip ahead to the section titled “Log Events”.

Then, change your Answers logFoo statements (where Foo is an Answers Event in the table above) to Analytics.logEvent using the appropriate event listed in the above table or your own custom event (use your own string instead of one of the constants available in the Firebase library).

The Analytics documentation shows parameters relevant to each predefined event, but you can always add customer parameters too. Instead of using one of the available constants, you can use any string you’d like. Then, register that parameter in the Firebase Console.

If an Analytics event is especially important to your business (such as a user spending money, or completing a critical flow in the app), you can configure it as a conversion.

Read more about how to log events (including how to attach relevant parameters) here.

Example Answers to Analytics Code

--- _static/diffs/PoemHistoryViewController_01.swift
+++ _static/diffs/PoemHistoryViewController_02.swift
@@ -2,14 +2,12 @@
         // Present the composer to the user.
         composer.show(from: self) { result in
             if result == .done {
-                // Log Answers Share event.
-                Answers.logShare(withMethod: "Twitter", contentName: poem.theme, contentType: "Poem", contentId: poem.UUID.description,
-                    customAttributes: [
-                        "Poem": poem.getSentence(),
-                        "Theme": poem.theme,
-                        "Length": poem.words.count,
-                        "Picture": poem.picture
-                    ]
-                )
+                // Log Analytics share event.
+                Analytics.logEvent(AnalyticsEventShare,
+                        parameters: [AnalyticsParameterContentType: "poem_image",
+                        AnalyticsParameterItemCategory: poem.theme,
+                        "method": "native_share",
+                        "length": poem.words.count,
+                        "picture": poem.picture])
             } else if result == .cancelled {
 ...

Next Steps

Use Firebase Authentication

In order to provide a seamless experience on mobile and a way to carry data from one device to another, we needed to provide a way for users to log in. Originally, Cannonball used Twitter and Digits to sign in. Now, Firebase Authentication handles these login methods and can easily be extended to handle more.

In Cannonball, we decided to use Phone Number Authentication and Anonymous Authentication.

To use Firebase Authentication in your app with a custom UI, follow the guide here. If you’d like to try a pre-built UI that already handles all of Firebase Authentication’s supported login flows (including phone number authentication), check out FirebaseUI.

Convert local storage of poems to use Firebase Realtime Database

Users can keep a history of the poems they created and share their favorites. In the old version of Cannonball, the poems were stored locally, but in the updated version, Cannonball uses the Firebase Realtime Database (RTDB) to persist poems across different devices. You can even log in on an iOS device, create a poem, and have that same poem appear on an Android device!

In the process of integrating the Realtime Database, we were able to get rid of a lot of code around local persistence. If we were concerned about offline capability in our app, it only takes a single line of code to turn that on in the RTDB SDK.

Here’s what we had to do in Cannonball to use the Realtime Database:

  • Enable the database in the Firebase Console
  • Remove PoemPersistence.swift module.
  • Change definition of a Poem so that it can serialize and deserialize to RTDB.
  • Set up basic RTDB security rules

Try other Firebase features

  • The open source FirebaseUI library contains helpful UI Bindings for the Firebase Realtime Database, as well as other Firebase services.
  • Try Firebase APIs by building projects with quickstart samples.