Listview 如果列表视图中的项目太多,为什么列表视图中的按钮会停止工作?

Listview 如果列表视图中的项目太多,为什么列表视图中的按钮会停止工作?,listview,button,swiftui,screen-size,vertical-scrolling,Listview,Button,Swiftui,Screen Size,Vertical Scrolling,救命啊!我搞不懂 为了帮助我学习SwiftUI,我正在使用列表视图制作一个简单的杂货清单应用程序。当点击列表中的每个项目时,按钮会变成绿色或红色 下面的代码非常有效,直到我向列表数组中添加了太多的项。如果列表的长度超过屏幕大小,你必须滚动,那么奇怪的事情就会开始发生。(例如按钮不会变为绿色,或者下一页上的项目变为绿色) 我用不同的模拟器进行了测试,在iphonese上,我可以在列表中找到14项,然后才开始出错。在iPhone11Pro Max上,我可以在列表中列出22项,然后再开始混乱。它与屏幕

救命啊!我搞不懂

为了帮助我学习SwiftUI,我正在使用列表视图制作一个简单的杂货清单应用程序。当点击列表中的每个项目时,按钮会变成绿色或红色

下面的代码非常有效,直到我向列表数组中添加了太多的项。如果列表的长度超过屏幕大小,你必须滚动,那么奇怪的事情就会开始发生。(例如按钮不会变为绿色,或者下一页上的项目变为绿色)

我用不同的模拟器进行了测试,在iphonese上,我可以在列表中找到14项,然后才开始出错。在iPhone11Pro Max上,我可以在列表中列出22项,然后再开始混乱。它与屏幕大小的长度以及是否需要滚动有关

代码如下:

    import SwiftUI

    struct CheckboxFieldView : View {
        @State var checkState:Bool = false ;
        var body: some View {
             Button(action:
                {
                    self.checkState = !self.checkState
            }) {
                       Rectangle()
                                .fill(self.checkState ? Color.green : Color.red)
                                .frame(width:20, height:20, alignment: .center)
                                .cornerRadius(5)
            }
            .foregroundColor(Color.white)
        }
    }

    struct ContentView: View {
    //    let items = (1...100).map { number in "Item \(number)" }

    let items = ["Bread", "Milk", "Cheese", "Granola", "Nuts", "Cereal", "Rosemary", "Tomato Sauce", "Bean with Bacon Soup", "Tea", "Chocolate Milk", "Frozen Blueberries", "Frozen Mixed Berries", "Frozen Strawberries", "Grapes"]

        var body: some View {
            NavigationView {
                List(items, id: \.self) { item in
                    HStack{
                        CheckboxFieldView()
                        Text(item)
                        self.padding()
                        Text ("Location")
                    }
                }.navigationBarTitle("Grocery List", displayMode: .inline)
            }
        }
    }

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

正如我看到的,
List
在滚动时有一些奇怪的行为,但有时它在设备上正常工作。尝试将
列表
替换为
滚动视图
,最后一个没有这些错误。

好吧,在这种情况下,这是一个建模问题。。。
@State
是视图状态属性,因此具有缓存视图的
列表
出于优化和重用目的,保留视图内部状态本身。因此,在这样的场景中,状态不能用于持久性目的,它需要有显式的视图模型,实际上它适用于所有模型情况

下面是修改后的演示代码,它使用基于
observeObject
@Binding
的视图模型进行视图间数据传递,可以正常工作

import SwiftUI
import Combine

// model to keep groceries
struct FoodItem: Identifiable {
    var id = UUID().uuidString
    var title: String
    var checked = false
}

// view model part 
class FoodViewModel: ObservableObject {
    @Published var items = [FoodItem]()
}

struct CheckboxFieldView : View {
    @Binding var item: FoodItem // bind to represented model
    var body: some View {
         Button(action:
            {
                self.item.checked.toggle()
        }) {
                   Rectangle()
                            .fill(self.item.checked ? Color.green : Color.red)
                            .frame(width:20, height:20, alignment: .center)
                            .cornerRadius(5)
        }
        .foregroundColor(Color.white)
    }
}

struct ContentView: View {

    @ObservedObject private var viewModel = FoodViewModel()
    let items = ["Bread", "Milk", "Cheese", "Granola", "Nuts", "Cereal", "Rosemary", "Tomato Sauce", "Bean with Bacon Soup", "Tea", "Chocolate Milk", "Frozen Blueberries", "Frozen Mixed Berries", "Frozen Strawberries", "Grapes"]

    init() {
        viewModel.items = items.map { FoodItem(title: $0) } // fill in demo model items
    }

    var body: some View {
        NavigationView {
            List(Array(viewModel.items.enumerated()), id: \.element.id) { (i, item) in
                HStack{
                    CheckboxFieldView(item: self.$viewModel.items[i]) // bind to current item in view model
                    Text(item.title)
                    Spacer()
                    Text ("Location")
                }
            }.navigationBarTitle("Grocery List", displayMode: .inline)
        }
    }
}

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

是的,阿斯佩里!这段代码解决了这个问题,非常感谢这个新手!我会研究你的模型,直到我完全理解。列表有一系列的格式,允许项目删除、移动、拖放等,而ScrollView没有,仅供参考。