SwiftUI:删除后更新NavigationView(iPad)

时间:2020-01-11 21:36:36

标签: swift swiftui swiftui-navigationlink

在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

3 个答案:

答案 0 :(得分:0)

您可以使用第二个选项进行列表更新: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.")
    }
    }

答案 1 :(得分:0)

从 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 :(得分:-1)

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

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
  }
}