我有一个一次性项目,试图使自己熟悉SwiftUI。本质上,我有各种类型的苹果,可以通过EnvironmentObject
变量来使用。该项目与我经历过的Landmarks教程相似,但我正在扩展诸如步进器和按钮等对象的使用。
我当前正试图拥有一个按钮,当按下该按钮时,保存某种苹果的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
}
Button
中AppleDetail
中的打印语句的输出为:
self.userData.appleId:无 self.userData.appleId:28EE7739-5E5A-4CA4-AFF5-7A6BFE025250
在Text
中显示self.userData.appleId
的{{1}}视图始终为ContentView
。任何帮助将不胜感激。
答案 0 :(得分:0)
在Beta 5中,ObservableObject
不再使用willChange
。它改为使用objectWillChange
。此外,它还可以自动合成主题,因此您不必自己编写主题(尽管您可以根据需要覆盖它)。
最重要的是,有一个新的属性包装器(@Published
),它将对属性进行更改以使发布者发出。无需手动调用.send()
,因为它将自动完成。因此,如果在您的代码中像这样重写UserData
类,它将正常工作:
final class UserData: ObservableObject {
@Published var apples = appleData
@Published var appleId = appleUUID
}