Firebase and the new SwiftUI 2 Application Life Cycle

SwiftUI 2

October 19, 2020 - 4 min read

For the longest time, iOS developers have used UIApplicationDelegate to handle application startup and other lifecycle events in their apps. At WWDC 2020, Apple made some significant changes to how apps participate in the application lifecycle.

In this article, we’re going to take a look at what this means for your Firebase apps. For a more in-depth look at the new application lifecycle, check out this other article I wrote recently.

When you create a new iOS app in Xcode, you will notice there are no AppDelegate or SceneDelegate classes any more. Instead, the main entry point to your app will look similar to this snippet:

import SwiftUI

@main
struct SwiftUIAppLifeCycleApp: App {
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }
}

This new approach falls in line with Apple’s move towards more declarative APIs. To learn more about its advantages and the impacts it has on your apps that use features like Siri, Handoff, Spotlight, or User Activity Continuation, check out The Ultimate Guide to the SwiftUI 2 Application Life Cycle.

If you use Firebase in your iOS apps, there are two main strategies you can follow.

Continue using the UIKit App Delegate Life Cycle

As of this writing, Apple hasn’t indicated that the UIKit App Delegate Life Cycle is deprecated. This is pretty good news and means you will be able to continue using the AppDelegate-based approach for initialising your app and handling life cycle events.

Here is a snippet from one of Firebase’s sample apps, to give you an impression of how that would look like:

import UIKit
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    FirebaseApp.configure()
    return true
  }
}

It’s also worth noting that Xcode 12 still allows you to create new apps using the UIKit App Delegate Life Cycle so that you can use this approach even for new apps, should you care to do so.

Creating a new SwiftUI project using the old life cycle
Creating a new SwiftUI project using the old life cycle

Start using the SwiftUI App Life Cycle

The new app life cycle is a step into the direction of using more and more domain-specific APIs. It comes with several benefits, such as more fine-grained control over where you’d like to handle deep links and user activity continuation.

Firebase, just like many other third-party SDKs and Frameworks, needs to be initialised early in the application life cycle. When using the new app life cycle, the earliest possible point to participate in the life cycle is by adding an initialiser to your app’s main entry point:

import SwiftUI
import Firebase

@main
struct SofiaApp: App {  
  init() {
    FirebaseApp.configure()
  }
  
  var body: some Scene {
    WindowGroup {
      MainScreen()
    }
  }
}

This approach works well for Firebase SDKs such as Cloud Firestore and Crashlytics.

For other Firebase SDKs, such as Firebase Cloud Messaging, this is not sufficient, as they use method swizzling to hook into the application life cycle. This mechanism allows frameworks to intercept calls to specific methods and handle them before passing the call on to your application.

In this case, you need to use the @UIApplicationDelegateAdaptor property wrapper to connect your app to an instance of AppDelegate.

Here is a template to get you started:

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    print("Colors application is starting up. ApplicationDelegate didFinishLaunchingWithOptions.")
    return true
  }
}

@main
struct ColorsApp: App {
  @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
  
  init() {
    FirebaseApp.configure()
  }
  
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }
}

This gives you the following benefits:

  1. You will be able to continue using frameworks that use method swizzling to participate in the application’s startup
  2. There’s a good chance you can just copy and paste your existing AppDelegate code
  3. You will be able to gradually migrate to the new app life cycle model (e.g. by handling deep links using the onOpenUrl modifier)

And that’s really it!

To give you a head start, I’ve updated the Colors sample app I used in the previous article to include Firebase Cloud Messaging.

I hope this article helped you to start using Firebase and Apple’s new app life cycle in your projects. Let me know which Firebase SDKs you use in your apps and if this helped you to migrate your app to SwiftUI 2. If you run into any issues, feel free to file an issue against our GitHub issue tracker

Thanks for reading!


The header image is based on Rocket by Icongeek26 on the Noun Project.