swift 显示体积(毫升/floz)

z9zf31ra  于 2023-04-19  发布在  Swift
关注(0)|答案(2)|浏览(104)

我希望有人能帮我解决这个让我抓狂的问题。
我想在Measurements中使用formatted()修饰符,这样我就可以得到特定于区域设置的单位,它对质量和温度非常有效。
我正确地得到了oz/g和F/C,但对于体积,我得到了cm 3/in 3而不是ml/floz。我意识到这是一个体积单位,但它不是我想要的。

Text("\(Measurement(value: Double(volume), unit: UnitVolume.milliliters).formatted())")
Text("\(Measurement(value: Double(mass), unit: UnitMass.grams).formatted())")
Text("\(Measurement(value: Double(temp), unit: UnitTemperature.celsius).formatted())")

我知道我能做到

Text("\(Measurement(value: Double(brew.water), unit: UnitVolume.milliliters).formatted(.measurement(width: .abbreviated, usage: .asProvided, numberFormatStyle: .number)))")

但是我必须自己找出语言环境。有没有办法用swiftui中的内置程序来实现这一点?
先谢谢你了

oaxa6hgo

oaxa6hgo1#

可以使用convertedMeasurementFormatter
在最简单的形式中,它看起来像

struct VolumeSampleView: View {
    let volume = Measurement(value: 10, unit: UnitVolume.liters)
    var body: some View {
        Text(volume.converted(to: .milliliters), formatter: MeasurementFormatter())
    }
}

但在extension中,您可以添加可重复使用的自定义,它的工作原理类似于formatted,但允许iOS 14+。

extension Formatter{
    static func measurement(unitOptions: MeasurementFormatter.UnitOptions = .providedUnit, unitStyle: Formatter.UnitStyle = .short, numberStyle: NumberFormatter.Style = .decimal) -> MeasurementFormatter{
        
        let f = MeasurementFormatter()
        f.unitOptions = unitOptions
        f.unitStyle = unitStyle
        
        let nf = NumberFormatter()
        nf.numberStyle = numberStyle
        
        f.numberFormatter = nf
        
        return f
    }
}

然后您的View将演变为类似于

struct VolumeSampleView: View {
    let volume = Measurement(value: 10, unit: UnitVolume.liters)
    let mass = Measurement(value: 10, unit: UnitMass.kilograms)
    var body: some View {
        Text(volume.converted(to: .milliliters), formatter: .measurement())
        Text(mass.converted(to: .grams), formatter: .measurement())

    }
}

您还可以扩展Measurement本身并添加一个自动提供字符串的方法。

extension Measurement{
    func toString(unitOptions: MeasurementFormatter.UnitOptions = .providedUnit, unitStyle: Formatter.UnitStyle = .short, numberStyle: NumberFormatter.Style = .decimal) -> String{
        
        let f = Formatter.measurement(unitOptions: unitOptions, unitStyle: unitStyle, numberStyle: numberStyle)
        return f.string(from: self)
    }
}

然后你不必使用formatter,你可以调用toString(),这将允许一个适用于所有SwiftUI版本的答案。

struct VolumeSampleView: View {
    let volume = Measurement(value: 10, unit: UnitVolume.liters)
    let mass = Measurement(value: 10, unit: UnitMass.kilograms)
    let temp = Measurement(value: 30, unit: UnitTemperature.fahrenheit)
    var body: some View {
        VStack{
            Text(volume.converted(to: .milliliters).toString())
            Text(volume.converted(to: .fluidOunces).toString())
            Text(mass.converted(to: .grams).toString())
            Text(temp.converted(to: .celsius).toString())
        }
    }
}

要显示区域设置调整的测量值,只需将.current添加到Locale

extension Formatter{
    static func measurement(unitOptions: MeasurementFormatter.UnitOptions? = .providedUnit, unitStyle: Formatter.UnitStyle = .short, numberStyle: NumberFormatter.Style = .decimal) -> MeasurementFormatter{
        
        let f = MeasurementFormatter()
        f.unitStyle = unitStyle
        
        if let options = unitOptions{ //Make unitOptions optional
            f.unitOptions = options
        }
        
        f.locale = .current //Add locale consideration

        let nf = NumberFormatter()
        nf.numberStyle = numberStyle
        
        f.numberFormatter = nf
        
        return f
    }
}
extension Measurement{
    func toString(unitOptions: MeasurementFormatter.UnitOptions? = .providedUnit, unitStyle: Formatter.UnitStyle = .short, numberStyle: NumberFormatter.Style = .decimal) -> String{
        
        let f = Formatter.measurement(unitOptions: unitOptions, unitStyle: unitStyle, numberStyle: numberStyle)
        return f.string(from: self)
    }
}

然后,当您希望单位按地区调整显示时,只需将unitOptions参数设置为nil

Text(volume.toString(unitOptions: nil)) //Will show locale specific version
6kkfgxo0

6kkfgxo02#

您的最后一次尝试很接近。只需将用法更改为.liquid而不是asProvided

Text("\(Measurement(value: Double(brew.water), unit: UnitVolume.milliliters).formatted(.measurement(width: .abbreviated, usage: .liquid, numberFormatStyle: .number)))")

这将给我的结果是“fl oz”,区域设置为en_US。
请注意,MeasurementFormatUnitUsage<UnitVolume>.liquid仅在iOS 16.0中可用,因此此解决方案不适用于iOS 15。

相关问题