如何在 Swift 中轻松格式化 UnitVolume 以使用公制和英制

问题描述 投票:0回答:1

我正在制作一些使用流体体积的东西,并希望使其适用于使用英制和公制的用户。

我目前在滑块上将公制转换为英制时遇到问题,

ClosedRange
最大化到错误的值。

我不完全确定我哪里出了问题,但也不知道这是否是处理问题的最佳方法。

我的思考过程是将所有内容都以公制存储,并为那些希望为他们转换英制 UI 的用户 - 因为公制是我的主要测量单位(并且对我来说更容易阅读)。

这是我正在使用的测试代码:

struct SettingsMenu: View {
  private let types: [UnitVolume] = [.milliliters, .fluidOunces]
  @State private var selectedUnitVolume: UnitVolume = .milliliters
  @State private var selectedGoal: Double = 2000

  var body: some View {
    Form {
      Section {
        Picker("Measurement unit", selection: $selectedUnitVolume) {
          ForEach(types, id: \.self) { type in
            Text(type.symbol).tag(type)
          }
        }
        .onChange(of: selectedUnitVolume) { _, newUnit in
          if newUnit == .milliliters {
            selectedGoal = Measurement(value: selectedGoal, unit: UnitVolume.fluidOunces).converted(to: .milliliters).value
          } else {
            selectedGoal = Measurement(value: selectedGoal, unit: UnitVolume.milliliters).converted(to: .fluidOunces).value
          }
        }

        VStack(alignment: .leading) {
          Label(label, systemImage: "drop.fill")
            Slider(value: $selectedGoal, in: range, step: step) {
              Text("Drink goal")
            } minimumValueLabel: {
              Text("\(Int(range.lowerBound))")
                .font(.footnote)
                .foregroundStyle(.gray)
            } maximumValueLabel: {
              Text("\(Int(range.upperBound))")
                .font(.footnote)
                .foregroundStyle(.gray)
            }
          }
        }
      }
  }

  var range: ClosedRange<Double> {
    selectedUnitVolume == .milliliters ? 100...5000 : 3...175
  }

  var step: Double {
    selectedUnitVolume == .milliliters ? 50 : 1
  }

  var label: String {
    let value = selectedUnitVolume == .milliliters ? selectedGoal : Measurement(value: selectedGoal, unit: UnitVolume.milliliters).converted(to: .fluidOunces).value.rounded()
    return "Daily saving goal: \(value.formatted(.number)) \(selectedUnitVolume.symbol)"
  }
}

结果如下:

如您所见,设备中的开关确实更新了滑块最小/最大的标签,但实际范围和

label
不正确。

swift swiftui foundation
1个回答
0
投票

你的代码的主要逻辑是好的。但这里有两个问题。

  • 您正在将显示的标签值转换两次。去掉标签函数中的转换

    var label: String {
        return "Daily saving goal: \(selectedGoal.formatted(.number)) \(selectedUnitVolume.symbol)"
    }
    
  • 您返回的毫升或液量盎司范围是错误的。 100 毫升不是 3 盎司,而是 33.81 盎司。上限为 169.07。

© www.soinside.com 2019 - 2024. All rights reserved.