2

环境: 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 后的运行时错误消息:

在此处输入图像描述


这里有一个线索: 在此处输入图像描述

4

1 回答 1

0

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
于 2019-07-27T23:03:59.980 回答