Home > Mobile >  SwiftUI toggles not changing when clicked on
SwiftUI toggles not changing when clicked on

Time:01-04

I'm trying to build a simple SwiftUI view that displays a number of toggles. While I can get everything to display ok, I cannot get the toggles to flip. Here's is a simplified code example:

import SwiftUI

class StoreableParam: Identifiable {
    let name: String
    var id: String { name }
    @State var isEnabled: Bool
    let toggleAction: ((Bool) -> Void)?
    
    init(name: String, isEnabled: Bool, toggleAction: ((Bool) -> Void)? = nil) {
        self.name = name
        self.isEnabled = isEnabled
        self.toggleAction = toggleAction
    }
}

class StoreableParamViewModel: ObservableObject {

    @Published var storeParams: [StoreableParam] = []
    init() {
                   
        let storedParam = StoreableParam(name: "Stored Param", isEnabled: false) { value in
            print("Value changed")
        }
        
        storeParams.append(storedParam)
    }
}

public struct UBIStoreDebugView: View {
    
    @StateObject var viewModel: StoreableParamViewModel
    public var body: some View {
        VStack {
            List {
                ForEach(viewModel.storeParams, id: \.id) { storeParam in
                    Toggle(storeParam.name, isOn: storeParam.$isEnabled)
                        .onChange(of: storeParam.isEnabled) {
                            storeParam.toggleAction?($0)
                        }
                }
            }
            
        }.navigationBarTitle("Toggle Example")
    }
}

CodePudding user response:

As mentioned in the comments, there are a couple of things going on:

  • @State is only for use in a View
  • Your model should be a struct

Then, you can get a Binding using the ForEach element binding syntax:

struct StoreableParam: Identifiable {
    let name: String
    var id: String { name }
    var isEnabled: Bool
    let toggleAction: ((Bool) -> Void)?
}

class StoreableParamViewModel: ObservableObject {

    @Published var storeParams: [StoreableParam] = []
    init() {
                   
        let storedParam = StoreableParam(name: "Stored Param", isEnabled: false) { value in
            print("Value changed")
        }
        
        storeParams.append(storedParam)
    }
}

public struct UBIStoreDebugView: View {
    
    @StateObject var viewModel: StoreableParamViewModel
    
    public var body: some View {
        VStack {
            List {
                ForEach($viewModel.storeParams, id: \.id) { $storeParam in
                    Toggle(storeParam.name, isOn: $storeParam.isEnabled)
                        .onChange(of: storeParam.isEnabled) {
                            storeParam.toggleAction?($0)
                        }
                }
            }
            
        }
    }
}
  • Related