iosobjective-cxcodensmeasurementformatternsmeasurement

Force NSMeasurementFormatter to get value over 1 with NSMeasurementFormatterUnitOptionsNaturalScale optiion


If we put the value 100g into a NSUnit and use NSMeasurementFormatterUnitOptionsNaturalScale to get a translated String, the result is 3.52 oz for Imperial system. The problem is with Metric, the result is 0,1 kg which is the good value but i need to keep 100g. It's for a recipe and and it's more common to keep "g" when the value is below 1 kg.

Tested with meters the problem don't exist, 100m is 100m in metric probably because meter is the base value like kg (and not g).

Is there a way to force it to have a value over 1 instead of 0,xx ?

NSUnitMass *g = [NSUnitMass grams];
NSMeasurement *measurementGramm = [[NSMeasurement alloc] initWithDoubleValue:100 unit:g];
NSMeasurementFormatter *formatter = [[NSMeasurementFormatter alloc] init];
[formatter setUnitOptions:NSMeasurementFormatterUnitOptionsNaturalScale];
NSLog(@"NSMeasurementFormatterUnitOptionsNaturalScale ---------- %@", [formatter stringFromUnit:g]);   

Solution

  • To make it easier, I assume that stored value is based on kg.

    NSMeasurement *measurement = [[NSMeasurement alloc] initWithDoubleValue:0.1 unit:NSUnitMass.kilograms];
    NSLog(@"Measurement value = %@", measurement);
    

    NSLog result

    Measurement value = <NSMeasurement: 0x28028ada0> value: 0.100000 unit: kg
    

    Here we can see that we have a value of 0.1 and unit in kg.

    It's for a recipe and and it's more common to keep "g" when the value is below 1 kg.

    We can convert the unit if the value is below 1

    NSMeasurementFormatter *formatter = [[NSMeasurementFormatter alloc] init];
    
    NSLog(@"Locale (KG) measurement value = %@", [formatter stringFromMeasurement:measurement]);
    
    if (measurement.doubleValue < 1.0) {
        NSLog(@"Locale (G) measurement value = %@", [formatter stringFromMeasurement:[measurement measurementByConvertingToUnit:NSUnitMass.grams]]);
    } else {
        NSLog(@"Locale (KG) measurement value = %@", [formatter stringFromMeasurement:measurement]);
    }
    

    NSLog result

    Locale (KG) measurement value = 0,1 kg
    Locale (G) measurement value = 0,1 kg
    

    The result is still in kg, this is caused by unitOptions

    By default, if unitOptions is set to the empty set, the formatter will do the following:

    • kilocalories may be formatted as "C" instead of "kcal" depending on the locale.
    • kilometersPerHour may be formatted as "miles per hour" for US and UK locales but "kilometers per hour" for other locales.

    We just have to change that

    formatter.unitOptions = NSMeasurementFormatterUnitOptionsProvidedUnit;
    
    if (measurement.doubleValue < 1.0) {
        NSLog(@"Locale (G) measurement value = %@", [formatter stringFromMeasurement:[measurement measurementByConvertingToUnit:NSUnitMass.grams]]);
    } else {
        NSLog(@"Locale (KG) measurement value = %@", [formatter stringFromMeasurement:measurement]);
    }
    

    NSLog result

    Locale (G) measurement value = 100 g
    

    Full code

    NSMeasurement *measurement = [[NSMeasurement alloc] initWithDoubleValue:0.1 unit:NSUnitMass.kilograms];
    NSLog(@"Measurement value = %@", measurement);
    
    NSMeasurementFormatter *formatter = [[NSMeasurementFormatter alloc] init];
    
    NSLog(@"Locale (KG) measurement value = %@", [formatter stringFromMeasurement:measurement]);
    
    if (measurement.doubleValue < 1.0) {
        NSLog(@"Locale (G) measurement value = %@", [formatter stringFromMeasurement:[measurement measurementByConvertingToUnit:NSUnitMass.grams]]);
    } else {
        NSLog(@"Locale (KG) measurement value = %@", [formatter stringFromMeasurement:measurement]);
    }
    
    formatter.unitOptions = NSMeasurementFormatterUnitOptionsProvidedUnit;
    
    if (measurement.doubleValue < 1.0) {
        NSLog(@"Locale (G) measurement value = %@", [formatter stringFromMeasurement:[measurement measurementByConvertingToUnit:NSUnitMass.grams]]);
    } else {
        NSLog(@"Locale (KG) measurement value = %@", [formatter stringFromMeasurement:measurement]);
    }