Using Firebase in the New Swift Lifecycle

Complete guide to configuring Firebase in modern Swift projects using the new app lifecycle where AppDelegate is no longer the entry point

Firebase in New Swift Lifecycle

Note:

This tutorial explains how to configure Firebase in modern Swift projects that use the new SwiftUI app lifecycle, where the traditional AppDelegate file is no longer the primary entry point.

Overview

Users who want to use Firebase in the new Swift lifecycle cannot find the AppDelegate file in the SDK guide. In the new cycle, you need to add the Firebase Configure command to the YourAppNameApp.swift file.

Reference:

Step 1: The New Swift App Lifecycle

With the introduction of SwiftUI, Apple introduced a new app lifecycle that replaces the traditional AppDelegate and SceneDelegate with a more streamlined approach.

The entry point of the app is now a struct conforming to the App protocol:

import SwiftUI

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

Step 2: Configuring Firebase

To configure Firebase, you need to call FirebaseApp.configure() before your app's UI is set up. In the new lifecycle, this is done in the initializer of your App struct.

import SwiftUI
import Firebase

@main
struct YourAppNameApp: App {
    
    // Add the initializer
    init() {
        FirebaseApp.configure()
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Step 3: Complete Implementation

Here’s the complete implementation for configuring Firebase in the new Swift app lifecycle:

import SwiftUI
import Firebase

@main
struct YourAppNameApp: App {
    
    // MARK: - Initializer
    
    init() {
        // Configure Firebase
        FirebaseApp.configure()
        
        // You can also configure other services here
        // For example, setting up Firestore settings
        setupFirestore()
    }
    
    // MARK: - Body
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
    
    // MARK: - Helper Functions
    
    private func setupFirestore() {
        let settings = Firestore.firestore().settings
        // Configure Firestore settings if needed
        // settings.isPersistenceEnabled = true
        // settings.cacheSizeBytes = FirestoreCacheSizeUnlimited
        Firestore.firestore().settings = settings
    }
}

Step 4: Using AppDelegate with the New Lifecycle

If you still need to use AppDelegate for specific functionalities (like push notifications), you can use the @UIApplicationDelegateAdaptor property wrapper.

1. Create an AppDelegate

Create a new AppDelegate.swift file:

import UIKit
import Firebase

class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Firebase is already configured in the App struct
        // You can perform other setup tasks here
        
        return true
    }
    
    // Add other AppDelegate methods as needed
    // For example, for push notifications:
    func application(_ application: UIApplication, 
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // Handle push notification registration
    }
}

2. Connect AppDelegate to Your App

In your YourAppNameApp.swift file, connect the AppDelegate using @UIApplicationDelegateAdaptor:

import SwiftUI
import Firebase

@main
struct YourAppNameApp: App {
    
    // Use the AppDelegate
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    init() {
        FirebaseApp.configure()
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Step 5: Advanced Configuration

Multiple Firebase Environments

For different environments (development, staging, production), you can use different configuration files.

  1. Add multiple .plist files to your project (e.g., GoogleService-Info-Debug.plist, GoogleService-Info-Release.plist)
  2. Configure based on build configuration:
init() {
    #if DEBUG
        let filePath = Bundle.main.path(forResource: "GoogleService-Info-Debug", ofType: "plist")
    #else
        let filePath = Bundle.main.path(forResource: "GoogleService-Info-Release", ofType: "plist")
    #endif

    guard let fileopts = FirebaseOptions(contentsOfFile: filePath!) else {
        assert(false, "Couldn't load config file")
        return
    }

    FirebaseApp.configure(options: fileopts)
}

Conditional Firebase Services

You can initialize Firebase services based on user preferences or other conditions:

init() {
    FirebaseApp.configure()
    
    if UserDefaults.standard.bool(forKey: "isAnalyticsEnabled") {
        // Initialize Firebase Analytics
    }
    
    if UserDefaults.standard.bool(forKey: "isCrashlyticsEnabled") {
        // Initialize Firebase Crashlytics
    }
}

Note:

Configuring Firebase in the new Swift app lifecycle is straightforward once you know where to place the initialization code. For more complex scenarios, you can still integrate AppDelegate using @UIApplicationDelegateAdaptor.