我编写了一个示例应用程序(适用于 macOS),其中包含 3 个用户。我对 NavigationSplitView 中的每个用户使用 NavigationLink。单击任何用户的导航链接时,详细视图应在编辑模式下显示用户名和年龄。它有效,但仅当第一个用户被单击时。如果我单击任何用户,则详细信息视图不会更改:它显示第一个用户数据。
我是 SwiftUI 的新手,我确信我误解了一些东西,但除了 SwiftUI 之外,我有 20 多年的编程经验。谢谢你的帮助。
我用谷歌搜索了几天,得到了很多好主意(尤其是来自 stackoverflow),但我无法解决我的问题。希望有人能解释我做错了什么。
// Create users array
class Users: ObservableObject {
@Published var users: [UserItem] = [
UserItem(id: 0, nickName: "Nick1", familyName: "Family1", firstName: "First1", age: 42),
UserItem(id: 1, nickName: "Nick2", familyName: "Family2", firstName: "First2", age: 39),
UserItem(id: 2, nickName: "Nick3", familyName: "Family3", firstName: "First3", age: 35)
]
}
// Define user properties
class UserItem: Identifiable, ObservableObject {
@Published var id:Int
@Published var nickName:String
@Published var familyName:String
@Published var firstName:String
@Published var age:Int
init(id:Int, nickName:String, familyName:String, firstName:String, age:Int) {
self.id = id
self.age = age
self.familyName = familyName
self.firstName = firstName
self.nickName = nickName
}
func fullName() -> String {
return "\(self.familyName) \(self.firstName) (\(self.nickName)) \(self.age)"
}
}
// Show users and their detail
struct Test2: View {
@StateObject var usersData = Users()
var body: some View {
NavigationSplitView {
List {
ForEach(usersData.users) { user in
NavigationLink {
UserDetailsView(user: user)
} label:{
Text(user.fullName())
}
}
Spacer()
}
} detail: {
Text("Select a user to edit.")
}
.padding()
.navigationTitle("Users")
}
}
// Show user detail
struct UserDetailsView: View {
@StateObject var user: UserItem
var body: some View {
VStack {
TextField("Family name", text: $user.familyName)
TextField("First name", text: $user.firstName)
TextField("Nick name", text: $user.nickName)
Stepper("Age: \(user.age)", value: $user.age)
Spacer()
// Check user property (live update))
Text(user.fullName())
}.padding()
}
}
#Preview {
Test2()
}
尝试使用 a
struct UserItem: Identifiable
(嵌套ObservableObject
可能会出现问题)和 a@Binding
inUserDetailsView
来编辑数据(双向绑定)。有关更详细的说明,请参阅此 官方链接,它为您提供了一些有关如何管理应用程序中的数据的好示例: 监控数据
也在ForEach 中绑定
在 MacOS 14.2 上,使用 Xcode 15.1,在真实的 ios17 设备(不是预览版)、MacCatalyst和 MacOS 14.2上进行了测试。在旧系统上可能会有所不同。请注意,它也可以使用
class UserItem: ObservableObject
.您遇到的主要问题是因为您使用了
@StateObject var user: UserItem
. 这样,“SwiftUI在声明状态对象的容器的生命周期内仅创建一次模型对象的新实例。”。这不是你想要的。请参阅: https: //developer.apple.com/documentation/swiftui/stateobject您的代码面临使用问题
ObservableObject
,StateObject
导致详细视图更新不正确。在修改后的代码中:UserItem
是一个结构体,而不是一个类,这使得它更适合 SwiftUI 的数据流。UserDetailsView
使用@Binding
forUserItem
,使其能够反映当前状态并传播更改。@StateObject
正确用于Users
保存用户数组的类。@State
管理用户选择,确保详细视图正确更新NavigationLink
。