83

现在AppDelegateandSceneDelegate已经从 SwiftUI 中删除了,我应该把以前在SceneDelegateand中的代码放在哪里AppDelegate,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
}
4

6 回答 6

75

这是 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()
        }
    }
}
于 2020-06-23T15:29:55.060 回答
72

覆盖您的初始化程序App也可以:

import SwiftUI
import Firebase

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

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

于 2020-06-24T19:45:40.323 回答
40

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

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

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

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

应用委托?

您可以拥有自己的自定义类并将其分配为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包装器

您可以直接将应用委托注入到@main结构中:

@UIApplicationDelegateAdaptor(CustomDelegate.self) var appDelegate

注意:使用AppDelegate

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

于 2020-07-13T16:17:44.310 回答
18

您还可以将新的 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/

于 2020-06-27T23:55:01.267 回答
2

请注意,以下方法将停止跨平台支持,因此仅应在您计划仅为 iOS 构建时使用。

还需要注意的是,这并没有使用 SwiftUI 生命周期方法,而是允许您返回到 UIKit 生命周期方法。

在 Xcode 12-beta 中创建 SwiftUI 应用程序时,您仍然可以拥有 AppDelegate 和 SceneDelegate。

您只需要确保在创建应用程序时为生命周期选择了正确的选项。

在此处输入图像描述

确保为生命周期选择UIKit App Delegate,您将获得 AppDelegate 和 SceneDelegate

于 2020-06-23T15:24:00.667 回答
1

我看到很多解决方案init被用作didFinishLaunching. 但是,在结构didFinishLaunching之后被调用。initApp

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()
      }
    }
  }
}
于 2021-05-18T00:19:18.433 回答