2010-02-24 8 views
10

Ich habe eine Entfernung als float und ich suche nach einer Möglichkeit, es für menschliche Leser gut zu formatieren. Idealerweise möchte ich, dass es von m nach km wechselt, wenn es größer wird, und um die Anzahl schön zu runden. In Meilen umzuwandeln wäre ein Bonus. Ich bin mir sicher, dass viele Leute ein solches Bedürfnis haben und ich hoffe, dass irgendwo Code herumläuft.Objective c string formatter für entfernungen

Hier ist, wie ich die Formate mag:

  • 0-100m: 47m (als ganze Zahl)
  • 100-1000m: 325m oder 320m (rund auf die nächsten 5 oder 10 Meter)
  • 1000-10000m: 1,2 km (Runde zur nächsten mit einer Nachkommastelle)
  • 10000m +: 21km

Wenn kein Code vorhanden ist, wie kann ich meine eigenen Formatierer schreiben ?

Dank

Antwort

24

Keine dieser Lösungen wirklich erfüllt, was sein I suchte, so baute ich auf sie:

#define METERS_TO_FEET 3.2808399 
#define METERS_TO_MILES 0.000621371192 
#define METERS_CUTOFF 1000 
#define FEET_CUTOFF  3281 
#define FEET_IN_MILES 5280 

- (NSString *)stringWithDistance:(double)distance { 
    BOOL isMetric = [[[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem] boolValue]; 

    NSString *format; 

    if (isMetric) { 
     if (distance < METERS_CUTOFF) { 
      format = @"%@ metres"; 
     } else { 
      format = @"%@ km"; 
      distance = distance/1000; 
     } 
    } else { // assume Imperial/U.S. 
     distance = distance * METERS_TO_FEET; 
     if (distance < FEET_CUTOFF) { 
      format = @"%@ feet"; 
     } else { 
      format = @"%@ miles"; 
      distance = distance/FEET_IN_MILES; 
     } 
    } 

    return [NSString stringWithFormat:format, [self stringWithDouble:distance]]; 
} 

// Return a string of the number to one decimal place and with commas & periods based on the locale. 
- (NSString *)stringWithDouble:(double)value { 
    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; 
    [numberFormatter setLocale:[NSLocale currentLocale]]; 
    [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; 
    [numberFormatter setMaximumFractionDigits:1]; 
    return [numberFormatter stringFromNumber:[NSNumber numberWithDouble:value]]; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    double distance = 5434.45; 
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]); 

    distance = 543.45; 
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]);  

    distance = 234234.45; 
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]);  
} 
+3

Ich mochte diese Lösung. Es wurde eine 'NSString + Entfernung'-Kategorie basierend darauf erstellt. Gist: https://gist.github.com/1397837 – Alex

+0

Danke das ist genau das, was ich für CLLocationDistance brauche. –

+0

Welche Lizenz/Begriffe sind mit dieser Kategorie verknüpft? Ich plane, es in meiner App zu verwenden. In meinen Lizenzen VC, möchten Sie ein Schiedsverfahren? – Andrew

17

Ja müssen Sie Ihre eigenen Formatierer schreiben, wie

#include <math.h> 
NSString* convertDistanceToString(float distance) { 
    if (distance < 100) 
     return [NSString stringWithFormat:@"%g m", roundf(distance)]; 
    else if (distance < 1000) 
     return [NSString stringWithFormat:@"%g m", roundf(distance/5)*5]; 
    else if (distance < 10000) 
     return [NSString stringWithFormat:@"%g km", roundf(distance/100)/10]; 
    else 
     return [NSString stringWithFormat:@"%g km", roundf(distance/1000)]; 
} 
... 
NSLog(@"The distance is %@", convertDistanceToString(1024)); 
+0

Vielen Dank für die Antwort, das war perfekt für das, was ich brauchte (und ersparte mir viel Zeit). –

2

Hier ist, wie ich es tun. Dies verwendet das Gebietsschema des Benutzers, um die Zeichenfolge richtig zu formatieren, was Sie wahrscheinlich auch tun sollten.

// Returns a string representing the distance in the correct units. 
// If distance is greater than convert max in feet or meters, 
// the distance in miles or km is returned instead 
NSString* getDistString(float distance, int convertMax, BOOL includeUnit) { 
    NSString * unitName; 
    if (METRIC) { 
    unitName = @"m"; 
    if (convertMax != -1 && distance > convertMax) { 
     unitName = @"km"; 
     distance = distance/1000; 
    } 
    } else { 
    unitName = @"ft"; 
    if (convertMax != -1 && distance > convertMax) { 
     unitName = @"mi"; 
     distance = distance/5280; 
    } 
    distance = metersToFeet(distance); 
    } 

    if (includeUnit) return [NSString stringWithFormat:@"%@ %@", formatDecimal_1(distance), unitName]; 

    return formatDecimal_1(distance); 

} 
// returns a string if the number with one decimal place of precision 
// sets the style (commas or periods) based on the locale 
NSString * formatDecimal_1(float num) { 
    static NSNumberFormatter *numFormatter; 
    if (!numFormatter) { 
    numFormatter = [[[NSNumberFormatter alloc] init] retain]; 
    [numFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; 
    [numFormatter setLocale:[NSLocale currentLocale]]; 
    [numFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; 
    [numFormatter setMaximumFractionDigits:1]; 
    [numFormatter setMinimumFractionDigits:1]; 
    } 

    return [numFormatter stringFromNumber:F(num)]; 

} 
+0

Vielen Dank. Ich hatte nicht daran gedacht, Lokalisierungen für die Zahlenformate zu verwenden.Ich muss mir die Zeit nehmen, dies dem Code hinzuzufügen, den ich benutzt habe. –

+0

Woher wissen Sie, ob der Benutzer METRIC möchte oder nicht? – ma11hew28

+0

Wenn sie nicht in den USA leben, verwenden wir standardmäßig metrisch. Und sie können es wechseln. Sie können NSLocale überprüfen, um ihren Standort zu erhalten. –

0

dies heute fand die gleiche Frage .... mit dem Gehen: in einem Verfahren

 
NSString *rvalue; 
    if (value > 1000) { 
     rvalue = [NSString stringWithFormat:@"%.02f km",value]; 
    }else { 
     rvalue = [NSString stringWithFormat:@"%.02f m",value]; 
    } 

könnte dies wickeln, wenn Bedarf

23

iOS 7 und OS X 10.9 eingeführt MKDistanceFormatter für Formatierung Entfernungen:

Codebeispiel:

double myDistance = 21837.0f; 

MKDistanceFormatter *df = [[MKDistanceFormatter alloc]init]; 
df.unitStyle = MKDistanceFormatterUnitStyleAbbreviated; 

NSLog(@"myDistance is %@", [df stringFromDistance: myDistance]); 

Update:

Es scheint, dass MKDistanceFormatter den Eingangswert irgendwie rundet. Z.B. wenn ich myDistance auf 111.0 setze, bekomme ich "100 m".

4

NSLengthFormatter, die mit iOS 8 und OS X 10.10 eingeführt wurde, ist eine Option, die Leute beachten sollten.

NSLengthFormatter *lengthFormatter = [[NSLengthFormatter alloc] init]; 
    lengthFormatter.unitStyle = NSFormattingUnitStyleShort; 

    NSLog(@"distance = %@", [lengthFormatter stringFromMeters:meters]); 

hat jedoch NSLengthFormatter nicht imperiale Einheiten in diesen Gegenden verwenden, wo sie bis auf Entfernungen Metrik verwenden.

+0

Das wäre nett, wenn es _feet_ statt _yards_ zurückgibt. – inorganik

-1

Für diejenigen, die eine schnelle 2.0-Version suchen. Von @MattDiPasquale

extension Double { 
    func toDistanceString() -> String { 
    let METERS_TO_FEET = 3.2808399 
    let METERS_CUTOFF = 1000.0 
    let FEET_CUTOFF = 3281.0 
    let FEET_IN_MILES = 5280.0 

    let format:String 
    if (NSLocale.isMetric()) { 
     if (self < METERS_CUTOFF) { 
     format = "\(self.stringWithDecimals(0)) metres" 
     } else { 
     format = "\((self/1000).stringWithDecimals(1)) km"; 
     } 
    } else { // assume Imperial/U.S. 
     let feet = self * METERS_TO_FEET; 
     if (feet < FEET_CUTOFF) { 
     format = "\(feet.stringWithDecimals(0)) feet"; 
     } else { 
     format = "\((self/FEET_IN_MILES).stringWithDecimals(1)) miles"; 
     } 
    } 
    return format 
    } 

    func stringWithDecimals(decimals:Int) -> String { 
    return String(format: "%.\(decimals)f", self) 
    } 
} 

extension NSLocale { 
    class func isMetric() -> Bool { 
    let locale = NSLocale.currentLocale() 
    return locale.objectForKey(NSLocaleUsesMetricSystem) as! Bool 
    } 
}