无法在视图之间共享环境
Posted
技术标签:
【中文标题】无法在视图之间共享环境【英文标题】:Unable to share environment between Views 【发布时间】:2019-07-27 22:49:10 【问题描述】:环境: Xcode 11.0 beta 4 (11M374r)
我无法与第二个视图共享“环境”。
我已经在 SceneDelegate 中实例化了环境 BindableObject:
SceneDelegate.swift:
我在基础视图 (ContentView) 和详细视图中都使用了 @EnvironmentObject。
环境已经在 SceneDelegate 中设置好了,所以它应该对所有视图都可用。
ContentView 确实看到了环境。 但是 DetailView 爆炸了:
这是完整的代码:
import Combine
import SwiftUI
struct UserInfo
var name: String
var message: String
init(name: String, msg: String)
self.name = name; self.message = msg
// A BindableObject is always a class; NOT a struct.
class UserSettings: BindableObject
let willChange = PassthroughSubject<Void, Never>()
var userInfo = UserInfo(name: "Ric", msg: "Mother had a feeling, I might be too appealing.")
didSet
willChange.send()
// =====================================================================================================
struct DetailView: View
@Binding var dismissFlag: Bool
@EnvironmentObject var settings: UserSettings // ...<error source>
var body: some View
VStack
Spacer()
Button(action: dismiss)
Text("Dismiss")
.foregroundColor(.white)
.padding()
.background(Color.green)
.cornerRadius(10)
.shadow(radius: 10)
Text("Hello")
Spacer()
private func dismiss()
settings.userInfo.message = "Rubber baby buggy bumpers."
dismissFlag = false
// ---------------------------------------------------------------------------
// Base View:
struct ContentView: View
@State var shown = false
@EnvironmentObject var settings: UserSettings
var body: some View
VStack
Spacer()
Button(action:
self.settings.userInfo.name = "Troglodyte"
self.settings.userInfo.message = "Top Secret"
self.shown.toggle()
)
Text("Present")
.foregroundColor(.white)
.sheet(isPresented: $shown) DetailView(dismissFlag: self.$shown)
.padding()
.background(Color.red)
.cornerRadius(10)
.shadow(radius: 10)
Text(self.settings.userInfo.message)
Spacer()
// =====================================================================================================
#if DEBUG
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
#endif
我错过了什么? 我做错了什么?
根据建议修订:
import SwiftUI
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate
var window: UIWindow?
var userSettings = UserSettings()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
// 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(userSettings))
self.window = window
window.makeKeyAndVisible()
他修改 SceneDelegate 后的运行时错误消息:
这里有一个线索:
【问题讨论】:
查看我编辑的答案以解决您的第二个问题。现在我知道为什么我没有花太多时间在预览上。 :-) 【参考方案1】:在SceneDelegate
中你需要声明你的变量的一个实例:
var userSettings = UserSettings() // <<--- ADD THIS
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
if let windowScene = scene as? UIWindowScene
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView()
.environmentObject(userSettings) <<-- CHANGE THIS
)
self.window = window
window.makeKeyAndVisible()
这会创建一个userSettings
的全局/环境实例。
编辑:
发生了第二个错误,与将您的 @EnvironmentObject
暴露给预览有关。根据this answer by @MScottWaller,您需要在SceneDelegate
和 PreviewProvider
中创建一个单独的实例。
#if DEBUG
struct ContentView_Previews : PreviewProvider
static var previews: some View
ContentView().environmentObject(UserSettings())
#endif
【讨论】:
根据您的建议进行更改。但我仍然收到运行时错误?(请参阅上面的修订版)。 这是一个不同的运行时错误。我不使用预览,所以请给我几分钟,我会编辑我的答案。以上是关于无法在视图之间共享环境的主要内容,如果未能解决你的问题,请参考以下文章
在视图之间的公共标题视图中设置共享标题;每个 Active View