代码之家  ›  专栏  ›  技术社区  ›  nevan king

用于距离的Objective c字符串格式化程序

  •  10
  • nevan king  · 技术社区  · 16 年前

    我有一个浮动的距离,我正在寻找一种方式,为人类读者很好地格式化它。理想情况下,当它变大时,我希望它从m变为km,并很好地将数字四舍五入。转换成英里数将是一种奖励。我相信很多人都需要这些,我希望有一些代码在某处浮动。

    以下是我想要的格式:

    • 100-1000米:325米或320米(精确到5米或10米)
    • 1000-10000m:1.2km(四舍五入,小数点后一位)
    • 10000米+:21公里

    如果没有可用的代码,如何编写自己的格式化程序?

    谢谢

    7 回复  |  直到 16 年前
        1
  •  25
  •   ma11hew28    15 年前

    这些解决方案中没有一个真正符合我的要求,因此我以它们为基础:

    #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]);    
    }
    
        2
  •  23
  •   Quinn Taylor    11 年前

    MKDistanceFormatter 有关设置距离的格式:

    代码示例:

    double myDistance = 21837.0f;
    
    MKDistanceFormatter *df = [[MKDistanceFormatter alloc]init];
    df.unitStyle = MKDistanceFormatterUnitStyleAbbreviated;
    
    NSLog(@"myDistance is %@", [df stringFromDistance: myDistance]);
    

    更新:

    似乎MKDestanceFormatter正在以某种方式舍入输入值。例如,当我将myDistance设置为111.0时,我得到“100米”。

        3
  •  17
  •   kennytm    16 年前

    是的,您需要编写自己的格式化程序,如

    #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));
    
        4
  •  4
  •   ThomasW    10 年前

    NSLengthFormatter 这是在iOS 8和OS X 10.10中引入的,这是人们应该注意的一个选项。

        NSLengthFormatter *lengthFormatter = [[NSLengthFormatter alloc] init];
        lengthFormatter.unitStyle = NSFormattingUnitStyleShort;
    
        NSLog(@"distance = %@", [lengthFormatter stringFromMeters:meters]);
    

    然而, has在使用公制单位(距离除外)的地区不使用英制单位。

        5
  •  2
  •   Andrew Johnson    16 年前

    我是这样做的。这将使用用户的区域设置来正确格式化字符串,您可能也应该这样做。

    // 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)];
    
    }
    
        6
  •  0
  •   mlecho    16 年前

    今天发现这个问题,问了同样的问题……接着:

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

        7
  •  -1
  •   Ciprian Rarau    11 年前

    对于那些寻找swift 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
      }
    }