通过在按钮中赋值更新环境对象变量



我有一个一次性项目,我正在使用它来尝试熟悉 SwiftUI。从本质上讲,我有各种类型的苹果,我通过EnvironmentObject变量提供。该项目与我所经历的地标教程相似,但我正在扩展步进器和按钮等对象的使用。

我目前正在尝试有一个按钮,当按下时,保存某种苹果的 UUID 并将其发送回原始视图。它不起作用,我也不确定为什么。这似乎是environmentObject分配无法逃脱action:关闭的问题.设置了打印语句和文本视图以显示某些点的变量值。虽然它似乎在闭包中设置了变量,但它并没有逃脱闭包,并且变量从未真正更新过。

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(UserData()))
self.window = window
window.makeKeyAndVisible()
}
}
struct AppleData: Codable, Hashable, Identifiable {
let id: UUID
var appleType: String
var numberOfBaskets: Int
var numberOfApplesPerBasket: [Int]
var fresh: Bool
static let `default` = Self(id: UUID(uuidString: "71190FD1-C8E0-4A65-996E-9CE84D200FBA")!,
appleType: "appleType",
numberOfBaskets: 1,
numberOfApplesPerBasket: [0],
fresh: true)  // for purposes of automatic preview
func image(forSize size: Int) -> Image {
ImageStore.shared.image(name: appleType, size: size)
}
}
let appleData: [AppleData] = load("apples.json")
var appleUUID: UUID?
func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
... // Code Omitted For Brevity
}
final class UserData: ObservableObject {
let willChange = PassthroughSubject<UserData, Never>()
var apples = appleData {
didSet {
willChange.send(self)
}
}
var appleId = appleUUID {
didSet {
willChange.send(self)
}
}
}
struct ContentView : View {
@EnvironmentObject private var userData: UserData
var body: some View {
NavigationView {
List {
ForEach(appleData) { apple in
NavigationLink(
destination: AppleDetailHost(apple: apple).environmentObject(self.userData)
) {
Text(verbatim: apple.appleType)
}
}
Text("self.userData.appleId:  (self.userData.appleId?.uuidString ?? "Nil")")
}
... // Code Omitted For Brevity
}
}
struct AppleDetail : View {
@EnvironmentObject var userData: UserData
@State private var basketIndex: Int = 0
var apple: AppleData
var totalApples: Int {
apple.numberOfApplesPerBasket.reduce(0, +)
}
var body: some View {
VStack {
... // Code Omitted For Brevity
}
Button(action: {
print("self.userData.appleId: (self.userData.appleId?.uuidString ?? "Nil")")
self.userData.appleId = self.apple.id
print("self.userData.appleId: (self.userData.appleId?.uuidString ?? "Nil")")
}) {
Text("Use Apple")
}
Text("self.apple.id: (self.apple.id.uuidString)")
Text("self.userData.appleId: (self.userData.appleId?.uuidString ?? "Nil")")
}
... // Code Omitted For Brevity
}

AppleDetailButton打印语句的输出为:

self.userData.appleId: nil self.userData.appleId: 28EE7739-5E5A-4CA4-AFF5-7A6BFE025250

ContentView中显示self.userData.appleIdText视图始终Nil。任何帮助将不胜感激。

在beta 5中,ObservableObject不再使用willChange。它改用objectWillChange。此外,它还会自动合成主题,因此您不必自己编写(尽管您可以根据需要覆盖它(。

最重要的是,有一个新的属性包装器(@Published(,它将对属性进行更改以使发布者发出。无需手动调用.send(),因为它将自动完成。因此,如果在代码中,像这样重写UserData类,它将正常工作:

final class UserData: ObservableObject {
@Published var apples = appleData
@Published var appleId = appleUUID
}

最新更新