英文:
Creating a custom FormatStyle for all Measurement Units
问题
我有一些测量值(比如UnitLength、UnitDuration、UnitSpeed等),对于大多数测量值,我想要使用提供的单位来进行格式化(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<UnitLength>) -> 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<Dimension> 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<Dimension> and Measurement<UnitDuration> 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<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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论