SwiftUI:在删除后更新NavigationView(iPad)

5

我希望在iPad上删除一行后能够显示空视图(这里是Text("请先选择一个人。"))。

当前情况: 在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示例。

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

但在删除行之后,仍然显示先前选择的详细视图(这里是:Paul):此处


请将图片粘贴到您的问题中。 - VillageTech
1
嗨@VillageTech,实际上我不能,因为这是我在这里的第一个问题,而发布图片需要10个问题后才能实现。抱歉。 - Julian Kahnert
好的,明白。 - VillageTech
你找到这个问题的解决办法了吗? - undefined
3个回答

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

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

这个过程过于复杂了,增加了太多状态和绑定属性。使用DetailView中用户列表的单个绑定可以达到相同的结果。 - Matteo Manferdini

-2

您可以使用第二个选项来更新列表: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的右侧仍会呈现先前选择的人的姓名。 - Julian Kahnert
那是给最后一个项目的。 - E.Coms
似乎鼓励使用自定义视图。 - E.Coms

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接