问题
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.
回答1:
Just create a Double extension to convert your meters unit to feet. Then just use MeasurementFormatter to display it as needed:
extension Double {
var metersToFeet: Double {
return Measurement(value: self, unit: UnitLength.meters)
.converted(to: .feet)
.value
}
}
Playground
extension Formatter {
static let measurement: MeasurementFormatter = {
let formatter = MeasurementFormatter()
formatter.locale = Locale(identifier: "en_US")
formatter.unitOptions = .providedUnit
formatter.numberFormatter.maximumFractionDigits = 0
formatter.unitStyle = .long
return formatter
}()
}
let meters: Double = 1839
let feet = Measurement(value: meters.metersToFeet, unit: UnitLength.feet)
let localizedString = Formatter.measurement.string(from: feet)
localizedString // // "6,033 feet"
or as suggested in comments by @Benjamin
let meters: Double = 1839
let measurement = Measurement(value: meters, unit: UnitLength.meters).converted(to: .feet)
let localizedString = Formatter.measurement.string(from: measurement)
print(localizedString) // "6,033 feet"
回答2:
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.
来源:https://stackoverflow.com/questions/39858828/choosing-units-with-measurementformatter