Создание пользовательского стиля формата для всех единиц измерения.

У меня есть несколько измерений (например,UnitLength, ,UnitSpeedи т. д.), и для большинства из них я хочу иметь форматтер, который использует предоставленный модуль (formatter.unitOptions = .providedUnit).

Чтобы упростить сайт вызова, я создал собственный FormatStyle — по длине он выглядит так:

      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)

Но если я хочу сделать то же самое дляUnitDuration, мне придется повторить этот код.

Я попробовал использовать вfunc format(), надеясь, что смогу использовать это для всех модулей, но компилятор жалуется:

Метод экземпляра «форматированный» требует типов Measurement<Dimension>и Measurement<UnitDuration>быть эквивалентным

Есть ли способ добиться этого, не повторяя код для каждогоUnit?

1 ответ

Вы можете передать общийDimensionвведите, а затем используйте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
Другие вопросы по тегам