2010-02-24 9 views
10

У меня есть расстояние как плавающее, и я ищу способ отформатировать его для читателей. В идеале, я бы хотел, чтобы он менялся от m до km по мере того, как он становился больше, и округлять число. Преобразование в мили было бы бонусом. Я уверен, что многие люди нуждаются в одном из них, и я надеюсь, что где-то есть какой-то код.Объект c string formatter для расстояний

Вот как я хотел бы форматы:

  • 0-100m: 47m (как целое число)
  • 100-1000m: 325m или 320m (округление до ближайших 5 или 10 метров)
  • 1000-10000m: 1.2km (округляется до ближайшего с одного знака после запятой)
  • 10000m +: 21km

Если нет никакого кода доступны, как я могу написать свой собственный форматировщик ?

Благодаря

ответ

24

Ни одно из этих решений действительно не встретил, что я искал, так что я построил на них:

#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

Мне понравилось это решение. Создал на его основе категорию «NSString + Distance». Gist: https://gist.github.com/1397837 – Alex

+0

Спасибо, это именно то, что мне нужно для CLLocationDistance. –

+0

Какие лицензии/термины связаны с этой категорией. Я планирую использовать его в своем приложении. В моих лицензиях VC, вы бы хотели арбитраж? – Andrew

17

Да, вы должны написать свой собственный форматер, как

#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

Большое спасибо за ответ, это было прекрасно для того, что мне было нужно (и сэкономило много времени). –

2

Вот как я это делаю. Это использует локаль пользователя для правильной форматирования строки, которую вы, вероятно, должны делать тоже.

// 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

Большое спасибо. Я не думал использовать локализацию для форматов чисел.Мне нужно потратить время, чтобы добавить это в код, который я использовал. –

+0

Откуда вы знаете, хочет ли пользователь METRIC или нет? – ma11hew28

+0

Если они не живут в США, мы по умолчанию используем метрику. И они могут переключать его. Вы можете проверить NSLocale, чтобы получить их местоположение. –

0

нашел это сегодня задают тот же вопрос .... пойду с:

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

может обернуть это в методе, в случае необходимости

23

IOS 7 и OS X 10.9 введена MKDistanceFormatter для форматирования расстояния:

Код Пример:

double myDistance = 21837.0f; 

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

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

Update:

Кажется, что MKDistanceFormatter округляет значение входного каким-то образом. Например. когда я устанавливаю myDistance на 111.0, я получаю «100 м».

4

NSLengthFormatter, который был представлен с iOS 8 и OS X 10.10, является опцией, о которой люди должны знать.

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

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

Однако NSLengthFormatter имеет не использует имперские единицы в тех районах, где они используют метрики для расстояний исключения.

+0

Было бы неплохо, если бы он вернул _feet_ вместо _yards_. – inorganik

-1

Для тех, кто ищет быструю версию 2.0. Портировано с @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 
    } 
}