Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI app life cycle iOS14 where to put AppDelegate code?

Now that AppDelegate and SceneDelegate are removed from SwiftUI, where do I put the code that I used to have in SceneDelegate and AppDelegate, Firebase config for ex?

So I have this code currently in my AppDelegate:

Where should I put this code now?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    
    FirebaseConfiguration.shared.setLoggerLevel(.min)
    FirebaseApp.configure()
    return true
}
like image 996
M1X Avatar asked Jun 23 '20 15:06

M1X


People also ask

Is there AppDelegate in SwiftUI?

You can still have an AppDelegate and a SceneDelegate when you create a SwiftUI app in Xcode 12-beta. You just need to make sure that you have chosen the correct option for the Life Cycle when you create your app.

What is use of AppDelegate in Swift?

Overview. Your app delegate object manages your app's shared behaviors. The app delegate is effectively the root object of your app, and it works in conjunction with UIApplication to manage some interactions with the system.

Where can I find AppDelegate M?

You can find it by searching UIApplicationDelegate in xcode search, then you will find the implemenation of this protocol in some file named as something.


4 Answers

Here is a solution for SwiftUI life-cycle. Tested with Xcode 12b / iOS 14

import SwiftUI
import UIKit

// no changes in your AppDelegate class
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print(">> your code here !!")
        return true
    }
}

@main
struct Testing_SwiftUI2App: App {

    // inject into SwiftUI life-cycle via adaptor !!!
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
like image 198
Asperi Avatar answered Oct 22 '22 04:10

Asperi


Overriding the initializer in your App also works:

import SwiftUI
import Firebase

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

Find a more detailed write-up here:

  • The Ultimate Guide to the SwiftUI 2 Application Life Cycle
  • Firebase and the new SwiftUI 2 Application Life Cycle
like image 36
Peter Friese Avatar answered Oct 22 '22 04:10

Peter Friese


You should not put that kind of codes in the app delegate at all or you will end up facing the Massive App Delegate. Instead, you should consider refactoring your code to more meaningful pieces and then put the right part in the right place. For this case, the only thing you need is to be sure that the code is executing those functions once the app is ready and only once. So the init method could be great:

@main
struct MyApp: App {
    init() {
        setupFirebase()
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

private extension MyApp {
    func setupFirebase() {
        FirebaseConfiguration.shared.setLoggerLevel(.min)
        FirebaseApp.configure()
    }
}

AppDelegate ?

You can have your own custom class and assign it as the delegate. But note that it will not work for events that happen before assignment. For example:

class CustomDelegate: NSObject, UIApplicationDelegate {
    static let Shared = CustomDelegate()
}

And later:

UIApplication.shared.delegate = CustomDelegate.Shared

Observing For Notifications

Most of AppDelegate methods are actually observing on notifications that you can observe manually instead of defining a new class. For example:

NotificationCenter.default.addObserver(
    self,
    selector: #selector(<#T##@objc method#>),
    name: UIApplication.didBecomeActiveNotification,
    object: nil
)

Native AppDelegate Wrapper

You can directly inject app delegate into the @main struct:

@UIApplicationDelegateAdaptor(CustomDelegate.self) var appDelegate

Note: Using AppDelegate

Remember that adding AppDelegate means that you are killing default multiplatform support and you have to check for platform manually.

like image 44
Mojtaba Hosseini Avatar answered Oct 22 '22 04:10

Mojtaba Hosseini


You can also use the new ScenePhase for certain code that the AppDelegate and SceneDelegate had. Like going to the background or becoming active. From

struct PodcastScene: Scene {
    @Environment(\.scenePhase) private var phase

    var body: some Scene {
        WindowGroup {
            TabView {
                LibraryView()
                DiscoverView()
                SearchView()
            }
        }
        .onChange(of: phase) { newPhase in
            switch newPhase {
            case .active:
                // App became active
            case .inactive:
                // App became inactive
            case .background:
                // App is running in the background
            @unknown default:
                // Fallback for future cases
            }
        }
    }
}

Example credit: https://wwdcbysundell.com/2020/building-entire-apps-with-swiftui/

like image 20
MScottWaller Avatar answered Oct 22 '22 04:10

MScottWaller