Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Choosing units with MeasurementFormatter

This is similar to a question I asked yesterday but the answer I got doesn't seem to work in this case.

I'm getting altitude values in meters from Core Location. I want to display these in a localized form. As an example, the altitude where I am right now is 1839m above sea level. This should be displayed as 6033 feet. The best I can do with MeasurementFormatter is "1.143 mi".

let meters : Double = 1839
let metersMeasurement = Measurement(value: meters, unit: UnitLength.meters)

let measurementFormatter = MeasurementFormatter()
measurementFormatter.locale = Locale(identifier: "en_US")

let localizedString = measurementFormatter.string(from: metersMeasurement)

The .naturalScale option that answered my previous question doesn't help here. I think this is a limitation of the framework, but I wonder if anyone has a workaround for now.

like image 895
Tom Harrington Avatar asked Oct 04 '16 17:10

Tom Harrington


People also ask

Which measurement units should you use?

Some of the most common are millimeters (mm), centimeters (cm), meters (m), and kilometers (km). So, which measurement units should you use? If something is VERY small (less than one centimeter), it makes the most sense to use the smallest unit, millimeters.

Why is it important to choose the correct units to use?

It's very important to choose the correct units to use when making a measurement, so that your measurements make sense and can be easily understood by other people. If you always use the appropriate units, then your measurements will be much easier to understand.

Why is it important to match the measurement unit to the quantity?

When measuring anything, you need to match the measurement unit to the size of the quantity you are trying to measure. In this lesson, learn about common measurement units for length and mass and how to know which one to use.

What are the different measurement units for length?

When measuring the length of something, you can use several different measurement units. Some of the most common are millimeters (mm), centimeters (cm), meters (m), and kilometers (km).


2 Answers

You just need to convert your UnitLength from meters to feet. You can also create a custom US measurement formatter to display it as needed:

extension Measurement where UnitType == UnitLength {
    private static let usFormatted: MeasurementFormatter = {
       let formatter = MeasurementFormatter()
        formatter.locale = Locale(identifier: "en_US")
        formatter.unitOptions = .providedUnit
        formatter.numberFormatter.maximumFractionDigits = 0
        formatter.unitStyle = .long
        return formatter
    }()
    var usFormatted: String { Measurement.usFormatted.string(from: self) }
}

Playground

let value: Double = 1839
let meters: Measurement<UnitLength> = .init(value: value, unit: .meters)
let feet = meters.converted(to: .feet)
let formatted = feet.usFormatted
print(formatted)    // "6,033 feet"\n
like image 71
Leo Dabus Avatar answered Sep 17 '22 01:09

Leo Dabus


I think you are correct there's no way to specify this kind of context. You could do something like:

extension MeasurementFormatter
{
    func altitudeString(from measurement: Measurement<UnitLength>) -> String
    {
        var measurement = measurement
        let unitOptions = self.unitOptions
        let unitStyle = self.unitStyle
        self.unitOptions = .naturalScale
        self.unitStyle = .long
        var string = self.string(from: measurement)
        if string.contains(self.string(from: UnitLength.miles))
        {
            self.unitStyle = unitStyle
            measurement.convert(to: UnitLength.feet)
            self.unitOptions = .providedUnit
            string = self.string(from: measurement)
        }
        else if string.contains(self.string(from: UnitLength.kilometers))
        {
            self.unitStyle = unitStyle
            measurement.convert(to: UnitLength.meters)
            self.unitOptions = .providedUnit
            string = self.string(from: measurement)
        }
        else
        {
            self.unitStyle = unitStyle
            string = self.string(from: measurement)
        }
        self.unitOptions = unitOptions
        return string
    }
}

Maybe there are other culturally specific ways of measuring elevation, but this would seem better than miles and kilometers.

like image 30
beyowulf Avatar answered Sep 21 '22 01:09

beyowulf