I have an Alarm struct, there is an Bool based on this I want to switch the toggle.
struct Alarm: Hashable {
var id: Int
var alarmTime: String
var selected: Bool
@Binding var isAlarmOn: Bool
init(id: Int, alarmTime: String, selected: Bool, isAlarmOn: Binding<Bool>) {
self.id = id
self.alarmTime = alarmTime
self.selected = selected
self._isAlarmOn = isAlarmOn
}
public var alarmId: Int {
get {
return self.id
}
set {
self.id = newValue
}
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func == (lhs: Alarm, rhs: Alarm) -> Bool {
return lhs.alarmId == rhs.alarmId
}
}
I have an AlarmModel, there is the Alarm's array.
class AlarmModel: ObservableObject {
@Published var alarms: [Alarm] = []
func addAlarm(_ alarmTime: String, _ alarmId: Int) {
let newAlarm = Alarm(id: alarmId, alarmTime: alarmTime, selected: false, isAlarmOn: .constant(false))
alarms.append(newAlarm)
}
//other functions...
}
And I have a ListView, this has the toggle that doesn't want to work the way I want it to.
struct AlarmListView: View {
@ObservedObject var alarmModel : AlarmModel
var body: some View {
List {
ForEach(alarmModel.alarms, id: \.self) { alarm in
HStack {
Toggle("", isOn: alarm.$isAlarmOn)
}
}
}
}
}
So if I use this sintax the code build, but Toggle doesn't do anything:
Toggle("", isOn: alarm.$isAlarmOn)
Else if I use this sintax: $alarm.isAlarmOn -> I get two errors:
- Cannot find '$alarm' in scope
- Failed to produce diagnostic for expression; please submit a bug report (https://swift.org/contributing/#reporting...
Thank you in advance for your help!
Change
@ObservedObject var alarmModel : AlarmModel
to a StateObject
@StateObject var alarmModel = AlarmModel()
And change
@Binding var isAlarmOn: Bool
To a published (in a class
@Published var isAlarmOn: Bool = false
So complete code is now working (as far I could test):
class Alarm: Hashable {
var id: Int
var alarmTime: String
var selected: Bool
@Published var isAlarmOn: Bool = false // @Binding var isAlarmOn: Bool
init(id: Int, alarmTime: String, selected: Bool, isAlarmOn: Bool) { // isAlarmOn: Binding<Bool>) {
self.id = id
self.alarmTime = alarmTime
self.selected = selected
self.isAlarmOn = isAlarmOn
// self._isAlarmOn = isAlarmOn
}
public var alarmId: Int {
get {
return self.id
}
set {
self.id = newValue
}
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func == (lhs: Alarm, rhs: Alarm) -> Bool {
return lhs.alarmId == rhs.alarmId
}
}
class AlarmModel: ObservableObject {
@Published var alarms: [Alarm] = []
func addAlarm(_ alarmTime: String, _ alarmId: Int) {
let newAlarm = Alarm(id: alarmId, alarmTime: alarmTime, selected: false, isAlarmOn: false) // , isAlarmOn: .constant(false))
alarms.append(newAlarm)
}
//other functions...
}
struct AlarmListView: View {
// @ObservedObject var alarmModel : AlarmModel
@StateObject var alarmModel = AlarmModel()
var body: some View {
List {
ForEach($alarmModel.alarms, id: \.self) { $alarm in
HStack {
Text(" \(alarm.alarmTime)")
Toggle("", isOn: $alarm.isAlarmOn)
}
}
}
.onAppear {
alarmModel.addAlarm("Alarm1", 1)
alarmModel.addAlarm("Alarm2", 2)
}
}
}
Note you can simplify a little, suppressing HStack:
ForEach($alarmModel.alarms, id: \.self) { $alarm in
Toggle("\(alarm.alarmTime)", isOn: $alarm.isAlarmOn)
}