[英]Where to configure Firebase in my iOS app in the new SwiftUI App life cycle without AppDelegate and SceneDelegate?
[英]SwiftUI app life cycle iOS14 where to put AppDelegate code?
現在AppDelegate
和SceneDelegate
已從 SwiftUI 中刪除,我將以前在SceneDelegate
和AppDelegate
中的代碼 Firebase 配置放在哪里?
所以我的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
}
這是 SwiftUI 生命周期的解決方案。 用 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()
}
}
}
在您的App
中覆蓋初始化程序也可以:
import SwiftUI
import Firebase
@main
struct BookSpineApp: App {
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
BooksListView()
}
}
}
在這里找到更詳細的文章:
您根本不應該將這種代碼放在應用程序委托中,否則您最終將面臨大規模應用程序委托。 相反,您應該考慮將代碼重構為更有意義的部分,然后將正確的部分放在正確的位置。 對於這種情況,您唯一需要做的就是確保在應用程序准備就緒后代碼正在執行這些功能並且只執行一次。 所以init
方法可能很棒:
@main
struct MyApp: App {
init() {
setupFirebase()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
private extension MyApp {
func setupFirebase() {
FirebaseConfiguration.shared.setLoggerLevel(.min)
FirebaseApp.configure()
}
}
您可以擁有自己的自定義 class 並將其指定為delegate
。 但請注意,它不適用於分配之前發生的事件。 例如:
class CustomDelegate: NSObject, UIApplicationDelegate {
static let Shared = CustomDelegate()
}
然后:
UIApplication.shared.delegate = CustomDelegate.Shared
大多數AppDelegate
方法實際上是在觀察您可以手動觀察的通知,而不是定義新的 class。 例如:
NotificationCenter.default.addObserver(
self,
selector: #selector(<#T##@objc method#>),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
AppDelegate
包裝器您可以直接將應用委托注入@main
結構:
@UIApplicationDelegateAdaptor(CustomDelegate.self) var appDelegate
AppDelegate
請記住,添加 AppDelegate 意味着您正在取消默認的多平台支持,並且您必須手動檢查平台。
您還可以將新的 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/
我還建議為此使用主App
的init
方法,因為它似乎可以安全使用(有任何異議嗎?)。
我通常做的可能有用的分享是擁有幾個實用程序類型,並結合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)
}
}
看起來很漂亮而且超級干凈。
我看到很多解決方案init
被用作didFinishLaunching
。 但是, didFinishLaunching
在App
結構的init
之后被調用。
相反,我們可以創建一個塊來在調用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()
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.