BGPicker.swift 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. // LoopFollow
  2. // BGPicker.swift
  3. import HealthKit
  4. import SwiftUI
  5. /// Lets the user pick a BG-related number (mg/dL or mmol/L) inside any form row.
  6. struct BGPicker: View {
  7. let title: String
  8. let range: ClosedRange<Double>
  9. @Binding var value: Double
  10. // MARK: – Helpers
  11. private var unit: HKUnit { Localizer.getPreferredUnit() }
  12. private var allValues: [Double] {
  13. if unit == .millimolesPerLiter {
  14. let step = 0.1
  15. let lower = ceil((range.lowerBound / 18) / step) * step
  16. let upper = floor((range.upperBound / 18) / step) * step
  17. return stride(from: lower, through: upper, by: step).map { $0 * 18 }
  18. } else {
  19. return Array(stride(from: range.lowerBound,
  20. through: range.upperBound,
  21. by: 1))
  22. }
  23. }
  24. private var snappedValue: Binding<Double> {
  25. Binding(
  26. get: { allValues.min(by: { abs($0 - value) < abs($1 - value) }) ?? value },
  27. set: { value = $0 }
  28. )
  29. }
  30. var body: some View {
  31. Picker(selection: snappedValue) {
  32. ForEach(allValues, id: \.self) { v in
  33. Text("\(Localizer.formatQuantity(v)) \(unit.localizedShortUnitString)")
  34. .tag(v)
  35. }
  36. } label: {
  37. Text(title)
  38. }
  39. }
  40. }