Reputation: 571
First let me show the sample code:
checkboxlist:
struct CheckListView: View {
var body: some View {
List(checkListData){ item in
CheckView(isChecked: item.isChecked, title: item.title)
}
.font(.title)
}
}
single checkbox:
struct CheckView: View {
@State var isChecked:Bool = false
var title:String
func toggle(){isChecked = !isChecked}
var body: some View {
HStack{
Button(action: toggle) {
Image(systemName: isChecked ? "checkmark.square" : "square")
}
Text(title)
}
}
}
the datas:
let checkListData = [
CheckListItem(id:0,title: "Neopolitan"),
CheckListItem(id:1,title: "New York"),
CheckListItem(id:2,title: "Hawaiian"),
.....
and the CheckListItem:
struct CheckListItem:Identifiable{
var id:Int
var isChecked: Bool = false
var title: String
}
I guess lots of guys already had this issue, suppose you have lots of checkboxes in you checkbox list which is enough to scroll, you check the first 1 or 2 or a few at the foremost of the list, then you scroll to the bottom, and scroll back again, those checked checkbox are turned back!
But, at this morning I suddenly found that if you use ForEach inside the List, then everything works fine:
List {
ForEach(checkListData, id: \.id){ item in
CheckView(isChecked: item.isChecked, title: item.title)
}
}.font(.title)
Can anyone explain why that weird issue happen and why this way is working fine? Thanks.
Upvotes: 0
Views: 132
Reputation: 2882
As @Asperi mentioned, List
is just like TableView
behind the scenes.So,Views
are reused when they go off screen.
To get your desired result, you have to maintain checked/unchecked state in your model class. Check the code below.
import SwiftUI
struct Test1: View {
@ObservedObject var items = CheckListItem()
var body: some View {
CheckView(items: items)
}
}
struct CheckView: View {
@ObservedObject var items: CheckListItem
var body: some View {
List(0..<items.model.count) { i in
HStack{
Button {
items.model[i].isChecked = !items.model[i].isChecked
} label: {
Image(systemName: items.model[i].isChecked ? "checkmark.square" : "square")
}
Text(items.model[i].title!)
}
}
}
}
struct Model:Identifiable {
var id:Int?
var isChecked: Bool = false
var title: String?
}
class CheckListItem:ObservableObject{
@Published var model:[Model] = []
init() {
createObjects()
}
func createObjects() {
for index in 0..<100{
model.append(Model(id: index, isChecked: false, title: "Neopolitan"))
}
}
}
Upvotes: 1