英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论