创建自定义的FormatStyle以适用于所有测量单位

huangapple go评论60阅读模式
英文:

Creating a custom FormatStyle for all Measurement Units

问题

我有一些测量值(比如UnitLengthUnitDurationUnitSpeed等),对于大多数测量值,我想要使用提供的单位来进行格式化(formatter.unitOptions = .providedUnit)。

为了简化调用位置,我创建了一个自定义的格式样式,对于长度,它看起来像这样:

struct ProvidedUnitFormatStyle: FormatStyle {
    func format(_ measurement: Measurement<UnitLength>) -> String {
        let formatter = MeasurementFormatter()
        formatter.unitOptions = .providedUnit
        return formatter.string(from: measurement)
    }
}

extension FormatStyle where Self == ProvidedUnitFormatStyle {
    static var providedUnit: ProvidedUnitFormatStyle { .init() }
}

// 使用方式:distance.formatted(.providedUnit)

但如果我想为UnitDuration做同样的事情,我将不得不重复这段代码。

我尝试在func format()中使用Measurement<Dimension>,希望能够将其用于所有单位,但编译器报错:

实例方法'formatted'要求类型Measurement<Dimension>Measurement<UnitDuration>等价

有没有一种方法可以在不重复为每个Unit编写代码的情况下实现这一点?

英文:

I have a few measurements (like UnitLength, UnitDuration, UnitSpeed etc) and for most of them I want to have a formatter that uses the provided unit (formatter.unitOptions = .providedUnit).

To simplify the call site, I created a custom FormatStyle - for length it looks like this:

struct ProvidedUnitFormatStyle: FormatStyle {
    func format(_ measurement: Measurement&lt;UnitLength&gt;) -&gt; String {
        let formatter = MeasurementFormatter()
        formatter.unitOptions = .providedUnit
        return formatter.string(from: measurement)
    }
}

extension FormatStyle where Self == ProvidedUnitFormatStyle {
    static var providedUnit: ProvidedUnitFormatStyle { .init() }
}

// usage: distance.formatted(.providedUnit)

But if I want to do the same for UnitDuration, I'll have to repeat this code.

I tried using Measurement&lt;Dimension&gt; in func format(), hoping I'll be able to use this for all units, but the compiler complains:

> Instance method 'formatted' requires the types Measurement&lt;Dimension&gt; and Measurement&lt;UnitDuration&gt; be equivalent

Is there a way to achieve this without repeating the code for every Unit?

答案1

得分: 1

You can pass a generic Dimension type and then use MeasurementFormatter.

struct ProvidedUnitFormatStyle<D: Dimension>: FormatStyle where D: Unit {
    func format(_ measurement: Measurement<D>) -> String {
        let formatter = MeasurementFormatter()
        formatter.unitOptions = .providedUnit
        return formatter.string(from: measurement)
    }
}

extension FormatStyle {
    static func providedUnit<D: Dimension>(for dimension: D.Type) -> Self where Self == ProvidedUnitFormatStyle<D> {
        return ProvidedUnitFormatStyle<D>()
    }
}

// Usage:
let distance = Measurement(value: 100, unit: UnitLength.meters)
let duration = Measurement(value: 60, unit: UnitDuration.seconds)

let distanceString = distance.formatted(.providedUnit(for: UnitLength.self))
let durationString = duration.formatted(.providedUnit(for: UnitDuration.self))
print(distanceString) // 100 m
print(durationString) // 60 sec
英文:

U can pass a generic Dimension type and then use MeasurementFormatter.

struct ProvidedUnitFormatStyle&lt;D: Dimension&gt;: FormatStyle where D: Unit {
    func format(_ measurement: Measurement&lt;D&gt;) -&gt; String {
        let formatter = MeasurementFormatter()
        formatter.unitOptions = .providedUnit
        return formatter.string(from: measurement)
    }
}

extension FormatStyle {
    static func providedUnit&lt;D: Dimension&gt;(for dimension: D.Type) -&gt; Self where Self == ProvidedUnitFormatStyle&lt;D&gt; {
        return ProvidedUnitFormatStyle&lt;D&gt;()
    }
}

// Usage:
let distance = Measurement(value: 100, unit: UnitLength.meters)
let duration = Measurement(value: 60, unit: UnitDuration.seconds)

let distanceString = distance.formatted(.providedUnit(for: UnitLength.self))
let durationString = duration.formatted(.providedUnit(for: UnitDuration.self)) 
print(distanceString) // 100 m
print(durationString) // 60 sec

huangapple
  • 本文由 发表于 2023年3月15日 18:07:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75743215.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定