swiftui - 无法在视图之间共享环境
问题描述
环境: Xcode 11.0 beta 4 (11M374r)
我无法用第二种观点分享“环境”。
我在 SceneDelegate 中实例化了环境 BindableObject:
我在基础(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 后的运行时错误消息:
这里有一个线索:
解决方案
在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
给预览有关。根据@MScottWaller 的这个答案,您需要在SceneDelegate
and PreviewProvider
中创建一个单独的实例。
#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
ContentView().environmentObject(UserSettings())
}
}
#endif
推荐阅读
- android - 单击 recyclerview 适配器中的第一项时,最后一项被删除
- java - 两台计算机的 Java unknownhostException
- c++ - 反转数组中的正序列
- visual-studio - Visual Studio 2017 和 Arduino
- angular - 使用 Angular 动画滑入和滑出组件
- java - 如何在 MyBatis 中将整数转换为枚举?
- recursion - 此函数中的 LEA 指令的目的是什么?整体递归的作用是什么?
- javascript - 在php while循环中单击按钮时获取特定的div
- youtube-api - 使用 JavaScript 以相同分辨率显示多个 YouTube 缩略图
- python - 如何避免我的 scipy 插值样条曲线添加无关的零?