SwiftUI-如何基于@ObservedObject为每个列表视图项创建编辑视图

时间:2020-09-18 09:09:01

标签: swiftui swiftui-navigationlink observedobject

我创建了一个简单的例子来说明我所面临的问题。我有两个视图,ListView和EditView。 ListView正在观察包含用户名列表的UsersViewModel(复数)。

使用NavigationLink,我想显示一个表单,在其中可以编辑用户名,这让我感到困惑。我已经创建了一个UserViewModel(单数形式),并具有EditView观察到的形式,但是当我尝试通过从ForEach循环中传递值的方式调用EditView时,由于我没有传递UserViewModel而收到类型不匹配错误。

也许我误解了可观察对象。我以为我可以在编辑表单上更改用户名,导航回列表视图,然后在列表中看到更改。

struct ListView: View {
    
    // Observe the Users View Model
    @ObservedObject var usersViewModel = UsersViewModel()
    
    var body: some View {
        
        NavigationView {
            List() {
                
                ForEach(usersViewModel.users) { user in

                    // FAILS with cannot converted "user" to expected type userViewModel
                    NavigationLink (destination: EditView(userViewModel: user)) {

                        Text("Hello \(user.name)")
                    }
                }
            }
            .navigationBarTitle("User List", displayMode: .inline)
            .onAppear(){
                usersViewModel.loadUsers()
            }

编辑视图

struct EditView: View {

  @ObservedObject var userViewModel: UserViewModel
     var body: some View {
         TextField("User Name", text: $userViewModel.user)

2 个答案:

答案 0 :(得分:0)

无法将“用户”转换为预期的类型userViewModel

您可能想在两个视图中使用相同的null(假设UserViewModel是一个结构)。

更改您的EditView以在初始化中使用user参数:

usersViewModel

并在父视图中传递它:

struct EditView: View {
  @ObservedObject var usersViewModel: UsersViewModel

否则,由于用户可能是结构,因此您将在子视图中修改用户的其他副本。

答案 1 :(得分:0)

我通过将usersViewModel传递给editView而不是pawello2222建议的userViewModel来解决了这个问题,但是显然您需要知道要编辑哪个元素。

所以我做到了;

       let users = usersViewModel.users.enumerated().map({ $0 })
        
        NavigationView {
            List() {
                ForEach(users, id: \.element.id ) { index, user in

                    NavigationLink (destination: EditView(userViewModel: usersViewModel, index: index)) {
                        

这似乎是long绕的,一定要枚举viewModel才能为EditView提供要编辑哪个元素的索引是不正确的方法?

它可以工作,但是我想知道正确的方法