SwiftUI New App lifecycle how to connect the Facebook SDK
Add UIApplicationDelegateAdaptor to your SwiftUI App
import SwiftUI
import Firebase
@main
struct SplitApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
WelcomeView()
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
ApplicationDelegate.shared.application(
application,
didFinishLaunchingWithOptions: launchOptions
)
FirebaseApp.configure()
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
ApplicationDelegate.shared.application(
app,
open: url,
sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
annotation: options[UIApplication.OpenURLOptionsKey.annotation]
)
}
}
}
How to add code to AppDelegate using SwiftUI Life Cycle
The init
might be too early, try in app delegate as follows
import GoogleMobileAds
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
GADMobileAds.sharedInstance().start(completionHandler: nil) // << here !!
return true
}
}
@main
struct YourApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
SwiftUI app life cycle iOS14 where to put AppDelegate code?
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()
}
}
}
How to Listen to new SwiftUI Lifecycle Methods in iOS 14?
You can get the APP LAUNCHING STATES (formerly done in AppDelegate) by being notified from the global environment variable and its property ".scenePhase
" like so:
// CREATE SOME APP LAUNCHING STATES LIKE WE HAD IN APPDELEGATE
@main
struct NewAppLifeCycleApp: App {
@Environment(\.scenePhase) var scenePhase
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { newScenePhase in
switch newScenePhase {
case .active:
print("App is active")
case .inactive:
print("App is inactive")
case .background:
print("App is in background")
@unknown default:
print("Interesting: Unexpected new value.")
}
}
}
}
If you want to integrate some code at a very early stage of your app, you can just add an init
-function:
// EASY WAY TO INTEGRATE SOME CODE INTO
// VERY EARLY STAGE OF APP INIT
@main
struct ColorsApp: App {
// Add an init method to add code
init() { print("My App is starting") }
var body: some Scene {
WindowGroup {
ContentView()
}
}
Swift UI Lifecycle: how to replace the current view with a new one ? Not simply pushing it
I see that you want to replace a root view of the app. Here is the simple example how to do it by using SwiftUI app life-cycle:
import SwiftUI
// Specify all root level screens
enum Screen {
case onboarding
case home
}
@main
struct MyApp: App {
// Use @State for current screen
@State var screen: Screen = .onboarding
var body: some Scene {
WindowGroup {
switch screen {
case .onboarding:
OnboardingView {
screen = .home
}
case .home:
HomeView()
}
}
}
}
struct OnboardingView: View {
let openHome: () -> Void
var body: some View {
VStack {
Text("OnboardingView")
Button("Open Home") {
openHome()
}
}
}
}
struct HomeView: View {
var body: some View {
Text("HomeView")
}
}
You can consider the MyApp: App
as a regular View
in SwiftUI
where you can replace any root views using state.
EDIT
This is an update version of the code. It's use very basic implementation of the Coordinator. Here Coordinator is also a factory for creating views. For more advanced info please search for MVVM with Coordinator specific for SwiftUI.
enum Screen {
case login
case users
}
final class AppCoordinator: ObservableObject {
@Published var screen: Screen = .login
private let userDefaultRepository = UserDefaultsRepository()
private let providerFactory: BaseProviderProtocol = BaseProviderFactory()
init() {
if userDefaultRepository.getAccessToken() != nil {
screen = .users
} else {
screen = .login
}
}
func userView() -> some View {
let store = UserStore()
let presenter = baseProviderFactory.getUserPresenter() as! BasePresenterProtocol
return UserView(store: store, presenter: presenter)
}
func loginView() -> some View {
let store = LoginStore()
let presenter = baseProviderFactory.getLoginPresenter() as! BasePresenterProtocol
return LoginView(store: LoginStore(), presenter: presenter)
}
}
@main
struct IosstarterkitApp: App {
@StateObject var coordinator = AppCoordinator()
var body: some Scene {
WindowGroup {
switch coordinator.screen {
case .login:
coordinator.loginView()
case .users:
coordinator.userView()
}
}
}
}
Accessing AppState in AppDelegate with SwiftUI's new iOS 14 life cycle
Use shared instance for AppState
class AppState: ObservableObject {
static let shared = AppState() // << here !!
// Singe source of truth...
@Published var user = User()
}
so you can use it everywhere
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject var appState = AppState.shared
// ... other code
}
and
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// ...and access appState here
AppState.shared.user = ...
}
How do you migrate to the new SwiftUI App Protocol?
You need to follow these steps to migrate a SwiftUI application to the new App
life cycle:
- Create a new
App
struct and add the@main
annotation:
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Remove the
@main
annotation fromAppDelegate
.Remove
Scene Configuration
fromInfo.plist
:
- (Optionally) Move
AppDelegate
/SceneDelegate
methods:
- SwiftUI app life cycle iOS14 where to put AppDelegate code?
- Is there any way to call SceneDelegate methods in iOS 14 app life cycle?
Now you can remove the
AppDelegate
andSceneDelegate
classes from the project (first make sure the app is indeed working as expected).Reinstall the app (as suggested in the comments).
Where to configure Firebase in my iOS app in the new SwiftUI App life cycle without AppDelegate and SceneDelegate?
There are three approaches for initialising third part frameworks in the new SwiftUI life cycle:
Using the old life cycle model
You can still use the old life cycle model:
Option 1: Use the UIKit App Delegate life cycle
When creating a new SwiftUI project, you can choose the old life cycle model. This will create an AppDelegate
and a SceneDelegate
as before. Not as fancy as using SwiftUI all the way, I admit - but definitely the easiest and most straightforward way.
Using the new life cycle model
If you want to use the new life cycle model, use either one of the following approaches.
Option 2: Use the App
's initialiser
You can override the default initialiser of your App
class, like this:
import SwiftUI
import Firebase
@main
struct SO62626652_InitialiserApp: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Option 3: Use @ UIApplicationDelegateAdaptor
In you App
class, define a property that holds a reference to your AppDelegate
, and let SwiftUI inject the AppDelegate
using the @ UIApplicationDelegateAdaptor
property wrapper, like this:
import SwiftUI
import Firebase
@main
struct SO62626652_AppDelegateAdaptorApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
Related Topics
Saving an Array of Nsurl to Nsuserdefaults
Getting The Parameterised Type of a Generic in Swift
Using Font Awesome Dynamically in Swift
How to Call Https Url in UIwebview (Swift)
Calculate Range of String from Word to End of String in Swift
How to Update Nslayoutconstraint in a UItableviewcell of Dynamic Height
Popping Noise Between Audioqueuebuffers
Xcode8 Beta 6 - Urlsession with Completionhandler Argument Not Working
What's The Correct Number Type for Financial Variables in Swift
Skease Action, How to Use Float Changing Action Setter Block
How to Send Multiple Buttons in Button.Addtarget Action? Swift3
Swift 4, Coreplot, Send Chart via Mail App (With Messageui)
Literal Numbers in Floatingpoint Protocol
Swiftui Custom View Repeat Forever Animation Show as Unexpected