firebase SwiftUI应用生命周期iOS14将AppDelegate代码放在哪里?

efzxgjgh  于 2023-08-07  发布在  Swift
关注(0)|答案(7)|浏览(141)

现在,AppDelegateSceneDelegate已经从SwiftUI中删除了,我应该把以前在SceneDelegateAppDelegate中的代码放在哪里,Firebase config for ex?
所以我的AppDelegate中有这个代码:
我现在应该把这个代码放在哪里?

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
}

字符串

eit6fx6z

eit6fx6z1#

这是SwiftUI生命周期的解决方案。使用Xcode 12 b/ 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()
        }
    }
}

字符串

t98cgbkg

t98cgbkg2#

覆盖App中的初始化器也可以工作:

import SwiftUI
import Firebase

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

字符串
在这里找到更详细的文章:

mwecs4sa

mwecs4sa3#

你不应该把这种代码放在应用委托中,否则你最终会面对Massive App Delegate。相反,您应该考虑将代码重构为更有意义的部分,然后将正确的部分放在正确的位置。对于这种情况,您唯一需要做的就是确保代码在应用程序准备就绪后执行这些函数,并且只执行一次。所以init方法可能很棒:

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

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

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

字符串

AppDelegate?

您可以拥有自己的自定义类并将其分配为delegate。但请注意,它不适用于在分配之前发生的事件。举例来说:

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


后来:

UIApplication.shared.delegate = CustomDelegate.Shared

观察通知

大多数AppDelegate方法实际上是在观察通知,你可以手动观察,而不是定义一个新的类。举例来说:

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

原生AppDelegate Package 器

你可以直接将app delegate注入到@main结构体中:

@UIApplicationDelegateAdaptor(CustomDelegate.self) var appDelegate

注意:使用AppDelegate

请记住,添加AppDelegate意味着您正在取消默认的多平台支持,并且您必须手动检查平台。

uhry853o

uhry853o4#

您还可以将新的ScenePhase用于AppDelegate和SceneDelegate具有的某些代码。就像去后台或变得活跃。起始

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
            }
        }
    }
}

字符串
信用示例:https://wwdcbysundell.com/2020/building-entire-apps-with-swiftui/

tjrkku2a

tjrkku2a5#

我看到很多解决方案都将init用作didFinishLaunching。但是,didFinishLaunchingApp结构的init之后被调用。

方案一

使用在App结构中创建的Viewinit。当App结构体的body被调用时,didFinishLaunching就发生了。

@main
struct MyApp: App {
  @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

  @ViewBuilder
  var body: some Scene {
    WindowGroup {
      MainView(appDelegate: appDelegate)
    }
  }
}

struct MainView: View {
  
  init(appDelegate: AppDelegate) {
    // at this point `didFinishLaunching` is completed
    setup()
  }
}

字符串

方案二

我们可以创建一个块来通知我们何时调用didFinishLaunching。这允许在SwiftUI世界中保留更多代码(而不是在AppDelegate中)。

class AppDelegate: NSObject, UIApplicationDelegate {

  var didFinishLaunching: ((AppDelegate) -> Void)?

  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions
      launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
  ) -> Bool {
    didFinishLaunching?(self)
    return true
  }
}

@main
struct MyApp: App {
  @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

  @ObservedObject private var applicationModel = ApplicationModel()

  // `init` gets called BEFORE `didFinishLaunchingWithOptions`
  init() {

    // Subscribe to get a `didFinishLaunching` call
    appDelegate.didFinishLaunching = { [weak applicationObject] appDelegate in

      // Setup any application code...
      applicationModel?.setup()
    }
  }

  var body: some Scene {
    return WindowGroup {
      if applicationObject.isUserLoggedIn {
        LoggedInView()
      } else {
        LoggedOutView()
      }
    }
  }
}

goucqfw6

goucqfw66#

我也会建议在使用主要的Appinit方法为这一个,因为它似乎安全使用(有异议吗?).
我通常做的,这可能是有用的分享,是有两个实用程序类型,结合Builder模式。

/// An abstraction for a predefined set of functionality,
/// aimed to be ran once, at app startup.
protocol StartupProcess {
    func run()
}

/// A convenience type used for running StartupProcesses.
/// Uses the Builder pattern for some coding eye candy.
final class StartupProcessService {
    init() { }

    /// Executes the passed-in StartupProcess by running it's "run()" method.
    /// - Parameter process: A StartupProcess instance, to be initiated.
    /// - Returns: Returns "self", as a means to chain invocations of StartupProcess instances.
    @discardableResult
    func execute(process: any StartupProcess) -> StartupProcessService {
        process.run()
        return self
    }
}

字符串
然后我们有一些过程

struct CrashlyticsProcess: StartupProcess {
    func run() {
        // Do stuff, like SDK initialization, etc.
    }
}

struct FirebaseProcess: StartupProcess {
    func run() {
        // Do stuff, like SDK initialization, etc.
    }
}

struct AppearanceCustomizationProcess: StartupProcess {
    func run() {
        // Do stuff, like SDK initialization, etc.
    }
}


最后,运行它们

@main
struct TheApp: App {
    init() {
        initiateStartupProcesses()
    }

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

private extension TheApp {
    func initiateStartupProcesses() {
        StartupProcessService()
            .execute(process: ExampleProcess())
            .execute(process: FirebaseProcess())
            .execute(process: AppearanceCustomizationProcess)
    }
}


看起来很不错,超级干净。

pjngdqdw

pjngdqdw7#

要使用SwiftUI生命周期,您需要使用UIApplicationDelegateAdaptor将符合UIApplicationDelegate的类的示例注入到SwiftUI应用程序中。
1.创建符合UIApplicationDelegate的AppDelegate类
1.在@main结构中使用UIApplicationDelegateAdaptor

// Class that conforms to UIApplicationDelegate
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // perform what you want here
        return true
    }
}

@main
struct MyApp: App {

    // Use UIApplicationDelegateAdaptor to inject an instance of the AppDelegate
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

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

字符串

Xcode 13更新

在Xcode 13中,你不能再选择生命周期,它是从你选择的接口推断出来的。
x1c 0d1x的数据

Xcode 12测试版

请注意,下面的方法将停止跨平台支持,因此只有在您计划仅为iOS构建时才应使用。
还应该注意的是,这并不使用SwiftUI生命周期方法,而是允许您返回到UIKit生命周期方法。
在Xcode 12-beta中创建SwiftUI应用时,仍然可以拥有AppDelegate和SceneDelegate。
您只需要确保在创建应用程序时,您已经为生命周期选择了正确的选项即可。



生命周期选择UIKit App Delegate,会得到AppDelegate和SceneDelegate

相关问题