带有 onDelete 的 Swiftui WatchKit List 和确认警报不会正确更新 tableview

Swiftui WatchKit List with onDelete and confirm alert does not update tableview correctly

有人可以为我指明正确的方向,告诉我如何使用确认删除功能实现简单的列表,或者至少在这里展示最佳实践。

如果警报部分被删除并且删除操作是立即执行的,则以下代码将起作用。 不知何故,确认警报的呈现使得删除操作出现在错误的人员名单上。第一次删除也会给出一个控制台警告:

[TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window.

但是,我不知道如何在不删除警报的情况下解决这个问题。顺便说一下,这个确切的代码在我的 mac 更新 xcode 之前的几周前工作,我相信。

import Foundation
import SwiftUI
import Combine

struct Person: Identifiable{
    var id: Int
    var name: String

    init(id: Int, name: String){
        self.id = id
        self.name = name
    }

}

class People: ObservableObject{
    @Published var people: [Person]


    init(){
        self.people = [
            Person(id: 1, name:"One"),
            Person(id: 2, name:"Two"),
            Person(id: 3, name:"Three"),
            Person(id: 4, name:"Four")]
    }

}

struct ContentView: View {
    @ObservedObject var mypeople: People = People()
    @State private var showConfirm = false
    @State private var idx = 0

    func setDeletIndex(at idxs:IndexSet) {
        self.showConfirm = true
        self.idx = idxs.first!
    }
    func delete() {
        self.mypeople.people.remove(at: idx)
    }
    var body: some View {
        VStack {
            List {

                Text("Currently \(mypeople.people.count) persons").font(.footnote)
                    .alert(isPresented: $showConfirm) {
                        Alert(title: Text("Delete"), message: Text("Sure?"),
                              primaryButton: .cancel(),
                              secondaryButton: .destructive(Text("Delete")) {

                                self.delete()
                            })
                }

                ForEach(mypeople.people){ person in
                    Text("\(person.name)")
                }.onDelete { self.setDeletIndex(at: [=10=]) }
            }
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

问题是由于关闭更新警报和删除列表记录的冲突。解决方法是延迟删除,如下所示(使用 Xcode 11.4 测试)

Text("Currently \(mypeople.people.count) persons").font(.footnote)
    .alert(isPresented: $showConfirm) {
        Alert(title: Text("Delete"), message: Text("Sure?"),
              primaryButton: .cancel(),
              secondaryButton: .destructive(Text("Delete")) {
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { // here !!
                    self.delete()
                }
            })
}