Пользовательская единица измерения

В iOS 10 Apple представила несколько компонентов для количественных измерений. Например:

let velocity = Measurement(value: 3, unit: UnitSpeed.metersPerSecond)

Несмотря на подробность, преимущества заключаются в том, что вы можете преобразовать в любую другую единицу без подверженных ошибкам встроенных вычислений:

// before
let velocityMetersPerSecond = 3.0
let velocityKilometersPerHour = velocityMetersPerSecond * 1000 / 60

// after
let velocityKilometersPerHour = velocity.converted(to: .kilometersPerHour)

В то время как Apple поддерживает многие устройства прямо из коробки, мне нужно устройство, которое они не поддерживают. Однако Apple помнила о расширяемости, и один из способов ввести новую метрику — расширить класс Unit:

extension UnitSpeed {
  static let furlongPerFornight = 
    UnitSpeed(symbol: "fur/ftn", converter: UnitConverterLinear(coefficient: 
      201.168 / 1209600.0)
}

Мне нужна скорость от источника в meters/second до единиц min/km. Следующая математика ниже показывает, как работает преобразование:

min / km = 1 / (m / s) * 1000 / 60

Проблема, с которой я столкнулся, заключается в том, как выразить мультипликативную обратную (или обратную) величину исходного значения в преобразовании. Вот ошибочная версия:

extension UnitSpeed {
  // still missing 1 / source value!
  static let minutesPerKilometer = UnitSpeed(symbol: "min/km",
    UnitConverterLinear(coefficient: 1000.0 / 60.0)
}

person Kelvin Lau    schedule 04.03.2018    source источник


Ответы (1)


Поскольку преобразование не является линейным, вам нужно будет создать свой собственный подкласс UnitConverter:

class UnitConverterInverse: UnitConverter {
    var coefficient: Double

    init(coefficient: Double) {
        self.coefficient = coefficient
    }

    override func baseUnitValue(fromValue value: Double) -> Double {
        return coefficient / value
    }

    override func value(fromBaseUnitValue baseUnitValue: Double) -> Double {
        return coefficient / baseUnitValue
    }
}

extension UnitSpeed {
    static let minutesPerKilometer = UnitSpeed(symbol: "min/km",
        converter: UnitConverterInverse(coefficient: 1000.0 / 60.0))
}

let velocity = Measurement(value: 60, unit: UnitSpeed.milesPerHour)

let velocity2 = velocity.converted(to: .minutesPerKilometer)

print(velocity2)
0.621371192237334 min/km
person vacawama    schedule 04.03.2018
comment
Вы меня опередили :) - Конечно, можно упростить двойные дроби, например. return coefficient/value - person Martin R; 04.03.2018