滚动列表中的项目时丢弃 SwiftUI 状态

SwiftUI state discarded when scrolling items in a list

我是 Swift 和 SwiftUI 的新手,所以对于这个非常基本的问题深表歉意。我一定是对 SwiftUI 生命周期及其与 @State 的交互有一些误解。

我有一个列表,当您单击该行时,它会增加一个计数器。如果我单击某些行项目以增加计数器,向下滚动并再次向上滚动 - 状态再次重置为 0。谁能指出我哪里出错了?非常感谢。

struct TestView : View {
    @State private var listItems:[String] = (0..<50).map { String([=10=]) }
    var body: some View {
        List(listItems, id: \.self) { listItem in
            TestViewRow(item: listItem)
        }
    }
}

struct TestViewRow: View {
    var item: String
    @State private var count = 0
    
    var body: some View {
        HStack {
            Button(item, action: {
                self.count += 1
            })
            Text(String(self.count))
            Spacer()
        }
    }
}

List 中的项目可能 延迟加载,具体取决于 os(macOS 与 iOS)的长度列表、屏幕上的项目数等

如果加载列表项然后更改其状态,并且该项目自 unloaded/reloaded 以来已进入 List

,则该状态不会重新分配给该项目

不是在每个 List 行上存储 @State,您可以将状态移动到不会被卸载的父视图:

struct ContentView : View {
    @State private var listItems:[(item:String,count:Int)] = (0..<50).map { (item:String([=10=]),count:0) }
    
    var body: some View {
        List(Array(listItems.enumerated()), id: \.0) { (index,item) in
            TestViewRow(item: item.item, count: $listItems[index].count)
        }
    }
}

struct TestViewRow: View {
    var item: String
    @Binding var count : Int
    
    var body: some View {
        HStack {
            Button(item, action: {
                count += 1
            })
            Text(String(count))
            Spacer()
        }
    }
}