【问题标题】:Deleting the last item in a list from the detail view in SwiftUI does not pop the detail view从 SwiftUI 的详细视图中删除列表中的最后一项不会弹出详细视图
【发布时间】:2020-12-13 22:58:55
【问题描述】:

我正在开发一个应用程序,在从详细视图中删除列表中的最后一项时遇到了 List 和 NavigationLink 的奇怪行为。我正在使用 iOS 13 和 Xcode 11,并制作了一个简化版本来重现该行为:

import SwiftUI

struct ListView: View {
    @State private var content = [Int](0..<10) {
        didSet {
            print(content)
        }
    }

    var body: some View {
        NavigationView {
            List(content, id: \.self) { element in
                NavigationLink(
                    destination: DetailView(
                        remove: {
                            DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + 1) { // Asynchronous network request
                                DispatchQueue.main.async {
                                    self.content.removeAll { $0 == element } // When request was successfull remove element from list
                                }
                            }
                        }
                    )
                ) {
                    Text("Element #\(element)")
                }
            }
        }
    }
}

struct DetailView: View {

    let remove: () -> Void

    init(remove: @escaping () -> Void) {
        self.remove = remove
    }

    var body: some View {
        VStack {
            Text("Hello world!")

            Button(
                action: {
                    self.remove()
                }
            ) {
                Image(systemName: "trash.circle")
                    .imageScale(.large)
            }
        }
    }
}

要重建错误,请选择列表中的最后一项,然后按垃圾桶删除。正如您可能注意到的那样,视图并没有像列表中的其他项目一样消失。但是,如果您按回,列表将正确删除最后一项。这也显示在此gif 中。按下垃圾桶时,列表的状态变化会打印到控制台。

我注意到移除特定项目似乎不是问题,因为移除随机项目时也会发生这种情况。如果我删除所选项目并在最后添加新项目,它确实可以正常工作。所以可能是缩小数组大小造成的。

我还找到了几种解决方法。就像用 .id(UUID()) 修改 NavigationView 一样,但这会删除动画。另一种解决方案是使用 PresentationMode 关闭视图并在消失时从列表中删除该项目,但我宁愿使用不同的解决方案。

为了查看它是否与 iOS 13 或 Xcode 11 有关,我在 iOS 14 和 Xcode 12 的最新 beta 版本(当前为 beta 5)上对其进行了测试。此处的详细视图不会因任何选定项目而消失。

以前有没有人遇到过这个问题,或者至少可以解释一下为什么会这样?

编辑:添加了模拟网络请求以更好地说明具体问题。

【问题讨论】:

    标签: ios swift swiftui swiftui-list swiftui-navigationlink


    【解决方案1】:

    我认为 SwiftUI 的行为有点奇怪......

    您可以明确告诉 SwiftUI 关闭 DetailView。为此,您需要稍微修改 DetailView:

    struct DetailView: View {
        @Environment(\.presentationMode) var presentationMode
        
        let remove: () -> Void
        
        init(remove: @escaping () -> Void) {
            self.remove = remove
        }
        
        var body: some View {
            VStack {
                Text("Hello world!")
                
                Button(
                    action: {
                        self.remove()
                        self.presentationMode.wrappedValue.dismiss()
                    }
                ) {
                    Image(systemName: "trash.circle")
                        .imageScale(.large)
                }
            }
        }
    }
    

    (另见:iOS SwiftUI: pop or dismiss view programmatically

    对我来说,这似乎可行,即使是最后一行。

    【讨论】:

    • 谢谢。这与我在帖子中已经提到的解决方案非常相似,并且效果很好。但我忘了包括删除实际上是由按下按钮时发生的网络请求触发的。我编辑了这个问题以更好地反映这一点。也许我可以在 .onRecieve 修饰符中做类似的事情。
    猜你喜欢
    • 2011-11-29
    • 2020-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多