【问题标题】:SwiftUI: Update NavigationView after deletion (iPad)SwiftUI:删除后更新 NavigationView (iPad)
【发布时间】:2020-01-11 21:36:36
【问题描述】:

我想在 iPad 上删除一行后显示 空视图(此处:Text("Please select a person."))。

目前: iPad 上的详细视图在删除项目后不会更新。 预期:在所选项目被删除后显示空视图

struct DetailView: View {
    var name: String
    var body: some View {
        Text("Detail of \(name)")
    }
}

struct MainView: View {
    @State private var users = ["Paul", "Taylor", "Adele"]

    var body: some View {
        NavigationView {
            List {
                ForEach(users, id: \.self) { user in
                    NavigationLink(destination: DetailView(name: user)) {
                        Text(user)
                    }
                }
                .onDelete(perform: delete)
            }
            Text("Please select a person.")
        }
    }

    func delete(at offsets: IndexSet) {
        users.remove(atOffsets: offsets)
    }
}

来自Hacking With Swift的NavigationView示例。

在下面的示例中,详细视图在第一次启动后正确显示:here

但删除一行后,之前选择的详细视图(这里:Paul)仍然显示:here

【问题讨论】:

  • 请将图片粘贴到您的问题中。
  • 嗨@VillageTech,实际上我不能,因为这是我在这里的第一个问题,并且可以在 10 个问题后发布图片。对不起
  • 好的,明白了。

标签: swift swiftui swiftui-navigationlink


【解决方案1】:

从 iOS 14 开始,似乎不支持从导航视图的列表中删除元素。

NavigationLink 类型采用 isActive 绑定,但在删除的情况下不起作用。当您收到.onDelete 回调时,为时已晚。 NavigationLink 不再在列表中,对您传递给它的绑定的任何更改都不会产生任何影响。

解决方法是将所有元素的绑定传递给DetailView,以便它可以验证元素是否存在并相应地显示一些内容。

struct DetailView: View {
    var name: String
    @Binding var users: [String]

    var body: some View {
        if users.contains(name) {
            Text("Detail of \(name)")
        } else {
            EmptyView()
        }
    }
}

struct MainView: View {
    @State private var users = ["Paul", "Taylor", "Adele"]

    var body: some View {
        NavigationView {
            List {
                ForEach(users, id: \.self) { user in
                    NavigationLink(destination: DetailView(name: user, users: $users)) {
                        Text(user)
                    }
                }
                .onDelete(perform: delete)
            }
        }
    }

    func delete(at offsets: IndexSet) {
        users.remove(atOffsets: offsets)
    }
}

【讨论】:

    【解决方案2】:

    您可以使用父视图的绑定来手动触发重新渲染(否则子视图不会收到通知):

    import SwiftUI
    
    struct DetailView: View {
      var name: String
      @Binding var notifier: Int
      @State var deleted: Bool = false
      
      var body: some View {
        Group {
          if !deleted {
            Text("Detail of \(name)")
              .onChange(of: notifier, perform: { _ in deleted = true })
          } else {
            Text("Deleted")
          }
        }
      }
    }
    
    struct MainView: View {
      @State private var users = ["Paul", "Taylor", "Adele"]
      @State private var deleteNotifier: Int = 0
    
      var body: some View {
        NavigationView {
          List {
            ForEach(users, id: \.self) { user in
              NavigationLink(destination: DetailView(name: user,
                                                     notifier: $deleteNotifier)) {
                Text(user)
              }
            }
            .onDelete(perform: delete)
          }
          Text("Please select a person.")
        }
      }
    
      func delete(at offsets: IndexSet) {
        users.remove(atOffsets: offsets)
        deleteNotifier += 1
      }
    }
    

    【讨论】:

    • 这太复杂了,添加了太多的状态和绑定属性。可以通过在DetailView 中与用户列表进行单个绑定来实现相同的结果。
    【解决方案3】:

    您可以使用第二个选项来更新列表:index。这样会加强清爽:

        var body: some View {
        NavigationView {
            List {
                ForEach(users.indices, id: \.self) { index in
                    NavigationLink(destination: DetailView(name: self.users[index])) {
                        Text(self.users[index])
                    }
                }
                .onDelete(perform: delete)
            }
            Text("Please select a person.")
        }
        }
    

    【讨论】:

    • 嗨@E.Coms,谢谢你的回答。你的例子似乎有同样的问题:如果你选择一个用户然后删除它,文本“请选择一个人”。将不再显示。相反,之前选择的人的姓名仍将显示在 iPad 的右侧。
    • 这是最后一项
    • 似乎鼓励您使用自定义视图
    猜你喜欢
    • 1970-01-01
    • 2020-10-30
    • 2019-11-24
    • 2022-09-23
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 2022-07-28
    相关资源
    最近更新 更多