简体   繁体   中英

SwiftUI picker value to reset if it goes beyond max

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.

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
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM