如何在 SwiftUI 中使用@EnvironmentObject 在 AppDelegate 和 SceneDelegate/Views 之间共享数据
How to use @EnvironmentObject to share data between AppDelegate and SceneDelegate/Views in SwiftUI
在 SwiftUI 5.1 中,我想使用 AppDelegate 创建一个 userData 对象。 userData 还将包含 BLE 广告数据,这些数据也将从 AppDelegate 更新。 UI 应该可以使用这些数据来显示这些值。
我在 AppDelegate 中使用
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
private var centralManager : CBCentralManager!
var userData: UserData!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
userData = UserData()
return true
}
在 SceneDelegate 中,我想使用
传递给视图
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
@EnvironmentObject var userData: UserData
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView:
BeaconList().environmentObject(userData)
)
self.window = window
window.makeKeyAndVisible()
}
}
编译工作正常,但是当 运行 我得到代码时
Thread 1: Fatal error: Reading EnvironmentObject outside
View.body
如果我删除
.environmentObject(userData)
我明白了
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
本质上,我试图从 AppDelegate 创建和更新 userData 对象,并从 SceneDelegate 显示并在下面查看。
我该如何实现?
也许您可以使用 UIApplication.shared.delegate
让 AppDelegate 访问用户数据:
class AppDelegate: UIResponder, UIApplicationDelegate {
var userData: UserData!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
userData = UserData()
return true
}
}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let userData = (UIApplication.shared.delegate as! AppDelegate).userData
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(userData))
self.window = window
window.makeKeyAndVisible()
}
}
在 SwiftUI 5.1 中,我想使用 AppDelegate 创建一个 userData 对象。 userData 还将包含 BLE 广告数据,这些数据也将从 AppDelegate 更新。 UI 应该可以使用这些数据来显示这些值。
我在 AppDelegate 中使用
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
private var centralManager : CBCentralManager!
var userData: UserData!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
userData = UserData()
return true
}
在 SceneDelegate 中,我想使用
传递给视图class SceneDelegate: UIResponder, UIWindowSceneDelegate {
@EnvironmentObject var userData: UserData
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView:
BeaconList().environmentObject(userData)
)
self.window = window
window.makeKeyAndVisible()
}
}
编译工作正常,但是当 运行 我得到代码时
Thread 1: Fatal error: Reading EnvironmentObject outside View.body
如果我删除
.environmentObject(userData)
我明白了
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
本质上,我试图从 AppDelegate 创建和更新 userData 对象,并从 SceneDelegate 显示并在下面查看。
我该如何实现?
也许您可以使用 UIApplication.shared.delegate
让 AppDelegate 访问用户数据:
class AppDelegate: UIResponder, UIApplicationDelegate {
var userData: UserData!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
userData = UserData()
return true
}
}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let userData = (UIApplication.shared.delegate as! AppDelegate).userData
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(userData))
self.window = window
window.makeKeyAndVisible()
}
}