Home > Blockchain >  Swift custom toggle style freezes UI
Swift custom toggle style freezes UI

Time:02-11

I would like to create a view with a list of checkboxes which I can select independently and keep track of these changes in an array. I have implemented some code to try and achieve this however Im experiencing weird behaviour where the screen freezes as a result of this code. Im still new to SwiftUI and reactive programming so I'm not sure if I am missusing reactive components.

When selecting the checkboxes the screen freezes and from there onwards I'm unable to click anything on the screen.

Entity

class Entity: Identifiable, Codable, Equatable {
    
    var id = UUID()
    let name: String
    var enabled: Bool
    
    init(name: String, enabled: Bool) {
        self.name = name
        self.enabled = enabled
    }
    
    static func == (lhs: Entity, rhs: Entity) -> Bool {
        lhs.id == rhs.id
    }
}

MyToggleStyle1

struct MyToggleStyle1: ToggleStyle {
    func makeBody(configuration: Configuration) -> some View {
        return HStack {
            configuration.label
            Image(systemName: configuration.isOn ? "checkmark.square" : "square")
                .resizable()
                .foregroundColor(configuration.isOn ? .green : .red)
                .frame(width: 22, height: 22)
                .onTapGesture { configuration.isOn.toggle() }
        }
    }
}

EntitySelectorView

struct EntitySelectorView: View {
    @State var customArray: [Entity] = [Entity(name: "All entities", enabled: false),
                                          Entity(name: "Boston Merchandising", enabled: false),
                                             Entity(name: "Canns & Co", enabled: false),
                                             Entity(name: "Sterling Auto Spares", enabled: false),
                                             Entity(name: "Compendia Bioscience Life Technologies", enabled: true),
                                             Entity(name: "Boston Consulting Group", enabled: false)]

    var body: some View {
        VStack(spacing: 0) {
            ScrollView(.vertical, showsIndicators: false) {
                    VStack{
                        ForEach($customArray) { $entity in
                            HStack {
                                Toggle(isOn: $entity.enabled) {
                                    Text(entity.name)
                                        .foregroundColor(Colors.darkTextColor.color)
                                        .font(.system(size: 16, weight: entity.name == "All entities" ? .bold : .regular, design: .default))
                                }
                                .toggleStyle(MyToggleStyle1())
                                
                                Spacer()
                            }.padding(.top, 12)
                        }
                        
                        Spacer()
                    }
                }

            Spacer()
        }.padding()
    }
}

enter image description here

CodePudding user response:

It is about model: 1st - it must be value, and 2nd - equatable should depend on any changed property.

Here is fixed part. Tested with Xcode 13.2 / iOS 15.2

demo

struct Entity: Identifiable, Codable, Equatable {   // << here !!

    var id = UUID()
    let name: String
    var enabled: Bool

    init(name: String, enabled: Bool) {
        self.name = name
        self.enabled = enabled
    }

    static func == (lhs: Entity, rhs: Entity) -> Bool {
        lhs.id == rhs.id && lhs.enabled == rhs.enabled   // << here !!
    }
}
  • Related