MeasurementFormatter для отображения футов и дюймов

Я играл с MeasurementFormatter чтобы попытаться отобразить имперские длины как 10"6' или же 10 ft 6 in безуспешно. LengthFormatter делает это правильно, когда isForPersonHeightUse установлен в true, но он плохо адаптируется к локали пользователя (т. е. в странах, где длина измеряется в метрической системе, за исключением случаев, когда речь идет о высоте). Есть ли способ заставить это поведение в форматере?

РЕДАКТИРОВАТЬ Этот вопрос, чтобы определить, как выбрать единицы измерения. Я могу выбрать футы или дюймы, но хочу отображать дробные футы в дюймах, например: 6'3"вместо 6.25 футов.

3 ответа

public struct LengthFormatters {

    public static let imperialLengthFormatter: LengthFormatter = {
        let formatter = LengthFormatter()
        formatter.isForPersonHeightUse = true
        return formatter
    }()

}

extension Measurement where UnitType : UnitLength {

    var heightOnFeetsAndInches: String? {
        guard let measurement = self as? Measurement<UnitLength> else {
            return nil
        }
        let meters = measurement.converted(to: .meters).value
        LengthFormatters.imperialLengthFormatter.string(fromMeters: meters)
    }

}

Пример использования:

    let a = Measurement(value: 6.34, unit: UnitLength.feet)
    print(a.heightOnFeetsAndInches ?? "")

    let b = Measurement(value: 1.5, unit: UnitLength.feet)
    print(b.heightOnFeetsAndInches ?? "")

Распечатает:

6 ft, 4.08 in
1 ft, 6 in

Как отображать футы и дюймы в SwiftUI

На случай, если кто-то придет сюда в поисках ответа SwiftUI.

      struct MeasurementTestView: View {
    @State private var height = Measurement(value: 68, unit: UnitLength.inches)
    
    var body: some View {
        VStack {
            Text(height, format: .measurement(width: .narrow, usage: .personHeight))
            Text(height, format: .measurement(width: .abbreviated, usage: .personHeight))
            Text(height, format: .measurement(width: .wide, usage: .personHeight))
        }
        .font(.title)
    }
}

Результат

Я изменил (упрощенный) ответ @maslovsa, чтобы удовлетворить мои потребности. У меня есть объект Core Data под названием "Пациент". У него есть параметр высоты в дюймах, который является Int64, Мне нужна строка, которую я показываю пользователю, так что вот мое свойство объекта пациента для этого:

var heightInFeetString : String {
    let measurement = Measurement(value: Double(self.height) / 12.0, unit: UnitLength.feet)
    let meters = measurement.converted(to: .meters).value
    return LengthFormatter.imperialLengthFormatter.string(fromMeters: meters)
}

Конечно, мне пришлось реализовать imperialLengthFormatter но я сделал это как продолжение LengthFormatter Сам, вот так:

extension LengthFormatter {
    public static let imperialLengthFormatter: LengthFormatter = {
        let formatter = LengthFormatter()
        formatter.isForPersonHeightUse = true
        return formatter
    }()    
}

Это на самом деле не снижает производительность, как это предлагается в комментариях к ответу @maslova. Поскольку свойство является статическим, оно инициализируется только один раз.

// When creating the Patient object
let patient = Patient(...) // Create in maanged object context
patient.height = 71

// Later displays in a collection view cell in a view controller
cell.heightLabel.Text = patient.heightInFeetString

Отображает это в ячейке моей таблицы:

5 футов, 11 дюймов

Другие вопросы по тегам