Search code examples
iosswiftcore-datansmeasurementformatter

NSMeasurementFormatter shows Imperial weights but not metric weights?


I have implemented an NSMeasurementFormatter and am having an odd issue. When the app is loaded as en_US, I get all my weights loaded into the text boxes as pounds, brilliant. However when I switch my app to en_GB and load the same data, i get nothing appearing in the text boxes.

When i print the objects the print out states the weights in kg so they are converting correctly, but they arent loading into the actual text boxes to be visible to the user.

Is there any clear cause to this? I have spent a few hours trying to work out why it works for one location but not the other! Appreciate the insight, here is the code:

Here is the initial save of an exercise where it either goes one way ot another depending on the apps setup at this point

        if self.localeIdentifier == "en_GB" {
            let kgWeight = Measurement(value: Double(self.userExerciseWeight.text!)!, unit: UnitMass.kilograms)
            newUserExercise.weight = kgWeight as NSObject?
            newUserExercise.initialMetricSystem = self.localeIdentifier
            print("SAVED AS \(localeIdentifier) METRIC")
        } else if self.localeIdentifier == "en_US" {
            let lbsWeight = Measurement(value: Double(self.userExerciseWeight.text!)!, unit: UnitMass.pounds)
            newUserExercise.weight = lbsWeight as NSObject?
            newUserExercise.initialMetricSystem = self.localeIdentifier
            print("SAVED AS \(localeIdentifier) IMPERIAL")
        }

Then here is my attempt to later reload this objects weight property

   let formatter = MeasurementFormatter()
    let exerciseWeight = userExercise.weight as! Measurement<Unit>
    let localeIdentifier = UserDefaults.standard.object(forKey: "locale")
    let locale = Locale(identifier: localeIdentifier as! String)
    formatter.locale = locale
    let numberFormatter = NumberFormatter()
    numberFormatter.maximumFractionDigits = 2
    formatter.numberFormatter = numberFormatter

    let finalWeight = formatter.string(from: exerciseWeight)
    cell.todaysExerciseWeightLabel.text = finalWeight 
}

So when set to US, i get a pounds readout to 2 decimal places, but when i set to GB i get nothing visible, i can just see it did the conversion in the print out of the object, pics below of the console that shows for loading both routines, and shots of the results:

enter image description here

enter image description here

enter image description here

UPDATED BELOW WITH MASSFORMATTER INFO

    let localeIdentifier = UserDefaults.standard.object(forKey: "locale") as! Locale
    let exerciseWeight = userExercise.weight as! Measurement<Unit>
    let formatter = MassFormatter()
    formatter.numberFormatter.locale = localeIdentifier
    formatter.numberFormatter.maximumFractionDigits = 2

    if localeIdentifier.usesMetricSystem {
        let kgWeight = exerciseWeight.converted(to: .kilograms)
        let finalKgWeight = formatter.string(fromValue: kgWeight.value, unit: .kilogram)
        cell.todaysExerciseWeightLabel.text = finalKgWeight
        print(formatter.string(fromValue: kgWeight.value, unit: .kilogram))
    } else {
        let kgWeight = exerciseWeight.converted(to: .pounds)
        let finalLbWeight = formatter.string(fromValue: exerciseWeight.value, unit: .pound)
        cell.todaysExerciseWeightLabel.text = finalLbWeight
        print(formatter.string(fromValue: exerciseWeight.value, unit: .pound))
    }
}

}


Solution

  • It all boils down to the following piece of code:

    let weight = Measurement(value: 10.0, unit: UnitMass.kilograms)
    
    let formatter = MeasurementFormatter()
    formatter.locale = Locale(identifier: "en_GB")
    
    print(formatter.string(from: weight))
    

    The result is an empty String (""). This is an obvious bug. Please, report it.

    A simple workaround is using the older MassFormatter:

    //let locale = Locale(identifier: "en_GB")
    let locale = Locale(identifier: "en_US")
    
    let weight = Measurement(value: 10.24, unit: UnitMass.pounds)
    
    let formatter = MassFormatter()
    formatter.numberFormatter.locale = locale
    formatter.numberFormatter.maximumFractionDigits = 2
    
    if locale.usesMetricSystem {
        let kgWeight = weight.converted(to: .kilograms)
        print(formatter.string(fromValue: kgWeight.value, unit: .kilogram))
    } else {
        print(formatter.string(fromValue: weight.value, unit: .pound))
    }