I have a custom SwiftUI picker. The picker takes two things: hour and minute. My struct has a value called maxDurationSeconds. My goal is, if the user selects a combination of hour and minute, which makes the overall go above the maxDurationSeconds, I want to reset both hour and minute to zero.
var body: some View {
let hours = [Int](0...maxHours)
let minutes = [Int](0...maxMinutes)
GeometryReader { geometry in
HStack(spacing: 0) {
Picker(selection: self.selection.hours, label: Text("")) {
ForEach(0..<maxHours, id: \.self) { index in
Text("\(hours[index]) hr")
.foregroundColor(Color(Asset.Color.V2.white.color))
}
}
.pickerStyle(.wheel)
.frame(width: geometry.size.width / 2, height: geometry.size.height, alignment: .center)
Picker(selection: self.selection.minutes, label: Text("")) {
ForEach(0..<maxMinutes, id: \.self) { index in
Text("\(minutes[index]) min")
.foregroundColor(Color(Asset.Color.V2.white.color))
}
}
.pickerStyle(.wheel)
.frame(width: geometry.size.width / 2, height: geometry.size.height, alignment: .center)
}
}
}
The rest of the struct is omitted since the file is huge. But here is the necessary info: We are getting a binding from selection, which has hour and minute in it. MaxHours and maxMinutes are 24 and 60.
This is what I am trying to achieve:
let hoursInSeconds = selection.hours.wrappedValue
let minutesInSeconds = selection.minutes.wrappedValue
if(hoursInSeconds minutesInSeconds > Int(maxDurationSeconds)) {
selection.hours.wrappedValue = 0
selection.minutes.wrappedValue = 0
}
I am not sure where to include this code. I tried doing on tap gesture of the picker views and doing this, but it would not update them. Any feedback is greatly appreciated.
CodePudding user response:
It can be done on change of selection
, like
GeometryReader { geometry in
HStack(spacing: 0) {
// ... content
}
.onChange(of: selection) { _ in // << assuming you confirm it to Equatable
// .onChange(of: [selection.hours, selection.minutes]) { _ in // << alternate
if(selection.hours selection.minutes > Int(maxDurationSeconds)) {
selection.hours = 0
selection.minutes = 0
}
}
}