【问题标题】:Complete list is recreates all views even if just one item has changed即使只有一项更改,完整列表也会重新创建所有视图
【发布时间】:2020-10-11 07:03:42
【问题描述】:

我有一个非常简单的 SwiftUI 列表视图的教科书示例,它从数组中的数据呈现项目。数组中的数据是可识别的。但是,当我更改数组中的数据、添加或删除一个项目时,列表视图中的所有行都会重新创建。那是对的吗?我的理解是 Identifiable 应确保仅重新创建列表中已更改的视图。

我的列表位于导航视图中,每一行都链接到详细视图。问题是,由于每次更改数据时列表中的所有项目都会被删除并重新创建,那么如果当我在详细视图中(它由通知触发)时发生这种情况,那么我会将其扔回列表中。

我错过了什么?

编辑:添加代码示例

这是我的数据结构:

struct Item: Identifiable {
    let id: UUID
    let name: String

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

这是我的 ItemView

struct ItemView: View {
    var item: Item

    init(item: Item) {
        self.item = item
        print("ItemView created \(self.item.id)")
    }

    var body: some View {
        Text(self.item.name)
    }
}

最后是我的列表视图:

struct KeyList: View {

    @State var items = [Item(name: "123"), Item(name: "456"), Item(name: "789")]

    var body: some View {
        VStack {
            List(self.items) { item in
                ItemView(item: item)
            }

            Button(action: {
                self.items.append(Item(name: "New"))
            }) {
                Text("Add")
            }
        }
    }
}

当我按下添加时,它将打印“ItemView created”4 次。我的理解是它应该只做1次?

【问题讨论】:

  • 你会显示代码吗?
  • @Alladinian 添加了一些代码。所以是的,我确实在 init 中生成了 UUID。但是我应该在哪里生成它呢?
  • 抱歉,我有别的想法。实际上,如果您在商品正文中打印类似的声明,您会看到只为新商品调用(这是您真正想要的)

标签: ios swift swiftui


【解决方案1】:

这是一个如何工作的示例。在 iOS 13.5 上测试并运行

仅删除一项时不会重新创建列表。这样就完成了。

关于 View 的弹出,这里已经回答了: SwiftUI ForEach refresh makes view pop

我在这里有一个解决这个问题的小方法。将要删除的项目添加到数组中。然后在返回时删除这些项目(这将使视图弹出)或以编程方式返回并且没有任何内容被删除

struct ContentView: View {
    
    @State var text:Array<String> = ["a", "b", "c"]
    
    
    var body: some View {
        NavigationView() {
            VStack() {
                List() {
                    ForEach(self.text, id: \.self){ item in
                        NavigationLink(destination: SecondView(textItem: item, text: self.$text)) {
                            Text(item)
                        }
                    }
                }
                
                Button(action: {
                    self.text.remove(at: 0)
                }){
                    Text("Remove \(self.text[0])")
                }
            }
        }
    }
    
}

struct SecondView: View {
    
    @State var textItem: String
    @Binding var text:  Array<String>
    
    @State var tmpArray: Array<String> = []
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
    var body: some View {
        VStack() {
            Text(self.textItem)
            
            Button(action: {
                //Append to a tmp array which will later be used to determine what to remove
                self.tmpArray.append(self.text[0])
            }){
                Text("Remove \(self.text[0])")
            }
            
            Button(action: {
                if self.tmpArray.count > 0 {
                    //remove your stuff which will automatically pop the view
                    self.text.remove(at: 0)
                } else {
                    // programmatically go back as nothing has been deleted
                    self.presentationMode.wrappedValue.dismiss()
                }
            }){
                Text("Go Back")
            }
        }
    }
    
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    相关资源
    最近更新 更多