2010-02-24 30 views
10

Tôi có một khoảng cách như một phao và tôi đang tìm kiếm một cách để định dạng nó độc đáo cho người đọc của con người. Lý tưởng nhất, tôi muốn nó thay đổi từ m đến km khi nó lớn hơn và làm tròn số độc đáo. Chuyển đổi sang dặm sẽ là một tiền thưởng. Tôi chắc rằng nhiều người đã có nhu cầu cho một trong những điều này và tôi hy vọng rằng có một số mã nổi xung quanh một nơi nào đó.Mục tiêu c chuỗi định dạng cho khoảng cách

Đây là cách tôi muốn các định dạng:

  • 0-100m: 47m (như một số nguyên)
  • 100-1000m: 325m hay 320m (vòng khi nó vượt mức 5 hoặc 10 mét)
  • 1000-10000m: 1.2km (tròn đến gần nhất với vị trí một số thập phân)
  • 10000m +: 21km

Nếu không có mã có sẵn, làm thế nào tôi có thể viết định dạng của riêng tôi ?

Cảm ơn

Trả lời

24

Không ai trong số các giải pháp này thực sự đã gặp những gì tôi đang tìm kiếm, vì vậy tôi xây dựng trên chúng:

#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

Tôi thích giải pháp này. Đã tạo danh mục 'NSString + Distance' dựa trên nó. Gist: https://gist.github.com/1397837 – Alex

+0

Cảm ơn đây chỉ là những gì tôi cần cho CLLocationDistance. –

+0

Giấy phép/điều khoản nào được liên kết với danh mục này. Tôi đang lên kế hoạch sử dụng nó trong ứng dụng của mình. Trong giấy phép của tôi VC, bạn có muốn trọng tài không? – Andrew

17

Có bạn cần phải viết formatter riêng của bạn, như

#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

Cảm ơn rất nhiều vì câu trả lời, điều này là hoàn hảo cho những gì tôi cần (và tiết kiệm rất nhiều thời gian). –

2

Đây là cách tôi làm điều đó. Điều này sử dụng ngôn ngữ của người sử dụng để định dạng đúng chuỗi, mà bạn có lẽ nên làm quá.

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

Cảm ơn rất nhiều. Tôi đã không nghĩ đến việc sử dụng nội địa hóa cho các định dạng số.Tôi sẽ phải dành thời gian để thêm mã này vào mã tôi đã sử dụng. –

+0

Làm cách nào để biết liệu người dùng có muốn METRIC hay không? – ma11hew28

+0

Nếu họ không sống ở Hoa Kỳ, chúng tôi sẽ mặc định số liệu. Và họ có thể chuyển đổi nó. Bạn có thể kiểm tra NSLocale để có được vị trí của họ. –

0

tìm thấy ngày hôm nay hỏi cùng một câu hỏi .... đi với:

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

có thể bọc này trong một phương pháp, nếu cần thiết

23

iOS 7 và OS X 10.9 giới thiệu MKDistanceFormatter cho khoảng cách định dạng:

Mã số Ví dụ:

double myDistance = 21837.0f; 

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

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

Cập nhật:

Dường như MKDistanceFormatter đang đi ngang các giá trị đầu vào bằng cách nào đó. Ví dụ. khi tôi đặt myDistance thành 111,0, tôi nhận được "100 m".

4

NSLengthFormatter được giới thiệu với iOS 8 và OS X 10.10 là một tùy chọn mọi người nên biết.

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

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

Tuy nhiên, NSLengthFormatter không sử dụng đơn vị Imperial ở những nơi họ sử dụng số liệu ngoại trừ khoảng cách.

+0

Điều này sẽ tốt đẹp nếu nó trả về _feet_ thay vì _yards_. – inorganik

-1

Đối với những người đang tìm kiếm một phiên bản 2.0 nhanh. Được chuyển từ @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 
    } 
} 
Các vấn đề liên quan