I have been playing with MeasurementFormatter
to try and display imperial lengths as 10'6"
or 10 ft 6 in
unsuccessfully. LengthFormatter
does this correctly when isForPersonHeightUse
is set to true
, but it does not adapt to the user's locale well (i.e. countries where length is measured in metric, except for when referring to height). Is there any way to force this behaviour in a formatter?
EDIT This question is to determine how to choose the units for a measurement. I am able to choose feet or inches, but want to display fractional feet as inches as in: 6'3" instead of 6.25 ft.
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)
}
}
Example of using:
let a = Measurement(value: 6.34, unit: UnitLength.feet)
print(a.heightOnFeetsAndInches ?? "")
let b = Measurement(value: 1.5, unit: UnitLength.feet)
print(b.heightOnFeetsAndInches ?? "")
Will print:
6 ft, 4.08 in
1 ft, 6 in
I modified (simplified) @maslovsa's answer to meet my needs. I have a Core Data object called "Patient". It has a height parameter in inches that is an Int64
. I want a string that I display to the user, so here's my property on my patient object for doing so:
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)
}
Of course, I had to implement the imperialLengthFormatter
as well, but I did it as an extension to LengthFormatter
itself, like this:
extension LengthFormatter {
public static let imperialLengthFormatter: LengthFormatter = {
let formatter = LengthFormatter()
formatter.isForPersonHeightUse = true
return formatter
}()
}
This actually doesn't kill performance as suggested in the comments for @maslova's answer. Due to the property being static, it only gets initialized once.
// 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
Displays this in my table cell:
5 ft, 11 in
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With