0

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.

enter image description here

1
  • This is not an issue. The views are reused in List (like in UITableView), you have to keep checked state in your model and only present it in view. Commented Jun 9, 2021 at 13:55

1 Answer 1

1

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"))
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.