iOS小技能:金额格式处理 (货币符号本地化)

2,258 阅读6分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

引言

iOS 系统自带格式化NSFormatter的常用子类有:NSNumberFormatter(数字格式化)、NSDateFormatter(NSISO8601DateFormatter日期格式化)、NSPersonNameComponentsFormatter(名片格式化)、NSMeasurementFormatter(数量单位格式化)。

在这里插入图片描述

本文侧重内容;金额格式处理的应用场景(根据需求格式化日期、数字,如商品的金额。)

在这里插入图片描述

原理:利用NSNumberFormatter进行处理

@interface NSNumberFormatter : NSFormatter {

I 金额的格式转化处理(NSNumberFormatter)

number format styles

 94863
 NSNumberFormatterNoStyle = kCFNumberFormatterNoStyle,

 94,862.57
 NSNumberFormatterDecimalStyle = kCFNumberFormatterDecimalStyle,

 ¥94,862.57
 NSNumberFormatterCurrencyStyle = kCFNumberFormatterCurrencyStyle,

 9,486,257%
 NSNumberFormatterPercentStyle = kCFNumberFormatterPercentStyle,

 9.486257E4
 NSNumberFormatterScientificStyle = kCFNumberFormatterScientificStyle,

 九万四千八百六十二点五七
 NSNumberFormatterSpellOutStyle = kCFNumberFormatterSpellOutStyle

1.1 获取货币符号

FOUNDATION_EXPORT NSLocaleKey const NSLocaleCurrencySymbol;      // NSString
//        获取货币符号的正确方式formatter.locale = [NSLocale currentLocale];
            NSString* currencySymbol = [NSLocale.currentLocale objectForKey:NSLocaleCurrencySymbol];//这里获取到的就是货币符号,例如:¥、$等等

去掉货币符号和负号

//

+ (NSString*)getAmountStr:(NSString*)topNO{
    NSLog( @"func: %s", __func__ );

    if([topNO containsString:@","] || [topNO containsString:@"," ]){
        
        return topNO;
        
    }
    
    
    NSString *tmp = [QCT_Common stringChangeMoneyWithStr:topNO numberStyle:NSNumberFormatterCurrencyStyle];

    
    if ([topNO doubleValue]<0) {// 去掉负号
        
//删除指定字符串的方法
        tmp=  [tmp stringByReplacingOccurrencesOfString:@"-" withString:@""];//
                
        
    }
    //去掉货币符号
                NSString* currencySymbol = [NSLocale.currentLocale objectForKey:NSLocaleCurrencySymbol];//这里获取到的就是货币符号,例如:¥、$等等

    tmp = [tmp stringByReplacingOccurrencesOfString:currencySymbol withString:@""];
    
    
    return tmp;
}


1.2 金额字段(简单处理)



    return  FMSTR(@"%0.2f",self.refundableAmount);// 金融字段处理
    //@property (nonatomic,assign)  double refundableAmount;//

. 避免出现这样的错误<total_fee><![CDATA[7.000000000000001]]></total_fee>

  • 元转分
/**
 元转分
 
 %d:整数
 %f:浮点数
 %s:方法
 %c:c字符
 %@:OC对象
 %p:指针
 //保留两位小数
 NSLog(@"%0.2f",1.0203);
 输出结果:1.02

 //使用0左补位
 NSLog(@"%04d",1);
 输出结果:0001

 //使用空格左补位
 NSLog(@"%4d",1);
 输出结果:   1

 //字符串补位
 NSLog(@"%4s!","a");
 输出结果:   a!

 //字符串右补位
 NSLog(@"%-4s!","a");
 输出结果:a   !

 <total_fee><![CDATA[7]]></total_fee>
 total_fee Int  类型
 */
+ (NSString*)changeY2FWithStr:(NSString*)paymentAmount{
    
    NSNumber *tm  = [NSNumber numberWithDouble:paymentAmount.doubleValue*100];
    return  FMSTR(@"%ld",(long)tm.integerValue);// 
    //    return  FMSTR(@"%0.2f",tm.doubleValue);//浮点数会报参数错误
    
}

1.3 金额字段(CurrencyStyle)

在这里插入图片描述

  • 用法
    //没有间隙的人民币符号:零售价:¥2.00
    //中文输入法的人民币符号:   ¥
    self.priceLab.text =[NSString stringWithFormat:@"%@%@",QCTLocal(@"retail_price_"),[QCT_Common  getAmountStr4CurrencyStyle:models.sysPrice]];


  • 金额的格式转化
风格对应的枚举输出样式
四舍五入的整数NSNumberFormatterNoStyle12346
小数形式NSNumberFormatterDecimalStyle12,345.678
货币形式(已本地化处理)NSNumberFormatterCurrencyStyle$12,345.68
百分数形式NSNumberFormatterPercentStyle1,234,568%
科学计数NSNumberFormatterScientificStyle1.2345678E4
朗读形式NSNumberFormatterSpellOutStyletwelve thousand three hundred forty-five point six seven eight
序数形式NSNumberFormatterOrdinalStyle12,346th
货币形式(已本地化处理)NSNumberFormatterCurrencyISOCodeStyleUSD12,345.68
货币形式(已本地化处理)NSNumberFormatterCurrencyPluralStyle12,345.68 US dollars
会计计数NSNumberFormatterCurrencyAccountingStyle$12,345.68

/**
 NSNumberFormatterCurrencyStyle 货币形式(已本地化处理)
 
 带货币符号
 //        获取货币符号的正确方式formatter.locale = [NSLocale currentLocale];
 //            NSString* currencySymbol = [NSLocale.currentLocale objectForKey:NSLocaleCurrencySymbol];//这里获取到的就是货币符号,例如:¥、$等等
         

 */
+ (NSString*)getAmountStr4CurrencyStyle:(NSString*)topNO{
    
    if([topNO containsString:@","] || [topNO containsString:@"," ]){
        
        return topNO;
        
    }
    
    
    NSString *tmp = [QCT_Common stringChangeMoneyWithStr:topNO numberStyle:NSNumberFormatterCurrencyStyle];
        
    if ([topNO doubleValue]<0) {// 去掉负号
        NSMutableString *tmpstr = [[NSMutableString alloc]initWithString:tmp];
        
//删除指定字符串的方法
        tmp = [tmpstr stringByReplacingOccurrencesOfString:@"-" withString:@""];//
    //   NSRange r1 = [tmp rangeOfString:currencySymbol];//查找字符串(返回一个结构体(起始位置及长度))
    // - (void)deleteCharactersInRange:(NSRange)range;//删除一个范围内的字符串

                
    }
    
    
    return tmp;
}


/**
 * 金额的格式转化
 * str : 金额的字符串
 * numberStyle : 金额转换的格式
 * return  NSString : 转化后的金额格式字符串
 
 /**
 * 94863
 * NSNumberFormatterNoStyle = kCFNumberFormatterNoStyle,
 
 * 94,862.57
 * NSNumberFormatterDecimalStyle = kCFNumberFormatterDecimalStyle,
 
 * ¥94,862.57
 * NSNumberFormatterCurrencyStyle = kCFNumberFormatterCurrencyStyle,
 
 * 9,486,257%
 * NSNumberFormatterPercentStyle = kCFNumberFormatterPercentStyle,
 
 * 9.486257E4
 * NSNumberFormatterScientificStyle = kCFNumberFormatterScientificStyle,
 
 * 九万四千八百六十二点五七
 * NSNumberFormatterSpellOutStyle = kCFNumberFormatterSpellOutStyle
 
 */
+ (NSString *)stringChangeMoneyWithStr:(NSString *)str numberStyle:(NSNumberFormatterStyle)numberStyle {
    
    // 判断是否null 若是赋值为0 防止崩溃
    if (([str isEqual:[NSNull null]] || str == nil)) {
        str = 0;
    }
    
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
    formatter.locale = [NSLocale currentLocale];
    formatter.numberStyle = numberStyle;
    // 注意传入参数的数据长度,可用double
    NSString *money = [formatter stringFromNumber:[NSNumber numberWithDouble:[str doubleValue]]];
    
    

    
    return money;
}



1.4 自定义格式:#,###.00元

在这里插入图片描述

原理:利用 NSNumberFormatter 的 numberStyle 和 positiveFormat 属性

//自定义格式:`#,###.00元`
- (NSString *)formatDecimalNumber:(NSString *)string {
 if (!string || string.length == 0) {
 return string;
 }
  
 NSNumber *number = @([string doubleValue]);
 NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
 formatter.numberStyle = kCFNumberFormatterDecimalStyle;
 //如果不用.00的样式,整数格式化后不会保留小数,因为kCFNumberFormatterDecimalStyle就是这样处理整数格式的。
 formatter.positiveFormat = @"#,##0.00元";
  
 NSString *amountString = [formatter stringFromNumber:number];
 return amountString;
}

1.5 其他样式

    // 小数点样式
    numberFormatter.decimalSeparator = @".";
    
    // 零的样式
    numberFormatter.zeroSymbol       = @"-";
    
    // 正前缀和后缀
    numberFormatter.positivePrefix = @"!";
    numberFormatter.positiveSuffix = @"元";
    // 负前缀和后缀
    numberFormatter.negativePrefix = @"@";
    numberFormatter.negativeSuffix = @"钱";
    // 整数最多位数
    numberFormatter.maximumIntegerDigits = 110;
    
    // 整数最少位数
    numberFormatter.minimumIntegerDigits = 2;
    
    // 小数位最多位数
    numberFormatter.maximumFractionDigits = 3;
    
    // 小数位最少位数
    numberFormatter.minimumFractionDigits = 1;
    
    // 数字分割的尺寸
    numberFormatter.groupingSize = 4;
    
    // 除了groupingSize决定的尺寸外,其他数字位分割的尺寸
    numberFormatter.secondaryGroupingSize = 2;
    
    // 最大有效数字个数
    numberFormatter.maximumSignificantDigits = 12;
    
    // 最少有效数字个数
    numberFormatter.minimumSignificantDigits = 3;
    // 四色五入方式
    numberFormatter.roundingMode = kCFNumberFormatterRoundHalfUp;

II 时间格式化(NSDateFormatter)

blog.csdn.net/z929118967/…

@interface NSISO8601DateFormatter : NSFormatter <NSSecureCoding> {

@interface NSDateFormatter : NSFormatter {

GGG: 公元时代,例如AD公元
yy: 年的后2位
yyyy: 完整年
MM: 月,显示为1-12
MMM: 月,显示为英文月份简写,如 Jan
MMMM: 月,显示为英文月份全称,如 Janualy
dd: 日,2位数表示,如02
d: 日,1-2位显示,如 2
EEE: 简写星期几,如Sun
EEEE: 全写星期几,如Sunday
aa: 上下午,AM/PM
H: 时,24小时制,0-23
K:时,12小时制,0-11
m: 分,1-2位
mm: 分,2位
s: 秒,1-2位
ss: 秒,2位
S:毫秒
zzz:三位字符串表示“时区”(例如GMT)。缩写 Z

2.1 系统自带的样式

date and time format styles

typedef NS_ENUM(NSUInteger, NSDateFormatterStyle) {    //     NSDateFormatterNoStyle = kCFDateFormatterNoStyle,
    NSDateFormatterShortStyle = kCFDateFormatterShortStyle,
    NSDateFormatterMediumStyle = kCFDateFormatterMediumStyle,
    NSDateFormatterLongStyle = kCFDateFormatterLongStyle,
    NSDateFormatterFullStyle = kCFDateFormatterFullStyle
};

格式日期时间
NSDateFormatterNoStyle""""
NSDateFormatterShortStyle2022/7/31上午11:40
NSDateFormatterMediumStyle2022年7月31日上午11:40:29
NSDateFormatterLongStyle2022年7月31日GMT+8 上午11:40:49
NSDateFormatterFullStyle2022年7月31日 星期三中国标准时间 上午11:41:16

2.2 自定义日期格式化

  1. 案例1: 小程序订单小票

在这里插入图片描述

  1. 案例2:订单详情时间格式化

在这里插入图片描述

setDateFormat

  1. stringFromDate:
  2. dateFromString:
+ (NSString *)date4ateFormat:(NSString *)DateFormat withdate:(NSDate *)date{
    
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateStyle:NSDateFormatterMediumStyle];
    [formatter setTimeStyle:NSDateFormatterShortStyle];
    [formatter setDateFormat:DateFormat];
    
    return [formatter stringFromDate:date];
}
//[QCT_Common dateWithFormatterString:tmpbirthday dateFormat:@"yyyy-MM-dd HH:mm:ss"]
+ (NSDate*)dateWithFormatterString:(NSString*)dateWithString dateFormat:(NSString*)dateFormat {
    
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
    dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
    dateFormatter.dateFormat = dateFormat;
    NSDate *date = [dateFormatter dateFromString:dateWithString];
    return date;
    
}

III 数量单位格式化

3.1 单位时间


/**
@property (class, readonly, copy) NSUnitDuration *hours;
@property (class, readonly, copy) NSUnitDuration *minutes;
@property (class, readonly, copy) NSUnitDuration *seconds;

*/
- (void)testNSUnitDuration{
    
    NSMeasurementFormatter *formatter = [[NSMeasurementFormatter alloc] init];
        [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh"]];

    [formatter setUnitOptions:NSMeasurementFormatterUnitOptionsProvidedUnit];

    
    
    NSMeasurement *measurement = [[NSMeasurement alloc] initWithDoubleValue:600 unit:NSUnitDuration.seconds];// 600秒

    NSMeasurement *measurement11 = [measurement measurementByConvertingToUnit:NSUnitDuration.minutes];//10分钟

    NSLog(@"seconds: %@",[formatter stringFromMeasurement:measurement]); //seconds: 600 sec

    
    NSLog(@"minutes: %@",[formatter stringFromMeasurement:measurement11]); //10 min
    
    NSMeasurement *measurement1 = [[NSMeasurement alloc] initWithDoubleValue:12 unit:NSUnitAcceleration.metersPerSecondSquared];
    NSLog(@"metersPerSecondSquared: %@",[formatter stringFromMeasurement:measurement1]); //12米/秒²

    
    NSMeasurement *measurement2 = [[NSMeasurement alloc] initWithDoubleValue:12 unit:NSUnitAcceleration.gravity];//
    NSLog(@"gravity: %@",[formatter stringFromMeasurement:measurement2]); //12G



}

列表对应类基础单位
加速度单位NSUnitAccelerationm /s²
几何角度单位NSUnitAngle度(°)
面积单位NSUnitArea平方米(m²)
单元集中质量(密度)NSUnitConcentrationMass毫克/分升(mg / dL)
单位分散NSUnitDispersion百万分率(ppm)
单位时间NSUnitDuration秒(s)
单位电荷NSUnitElectricCharge库仑(C)
单位电流NSUnitElectricCurrent安(A)
单位电位差(电压)NSUnitElectricCurrent伏特(V)
单元电阻NSUnitElectricResistance欧姆(Ω)
单位能量NSUnitEnergy焦耳(J)
单位频率NSUnitFrequency赫兹(赫兹)
单位燃料效率NSUnitFuelEfficiency每百公里升(L / 100km)
单位长度NSUnitLength米(m)
单位照度NSUnitIlluminance勒克斯(lx)
单位质量NSUnitMass千克(kg)
单位功率NSUnitPower瓦特(W)
单位压力(压强) NSUnitPressure牛顿每平方米(N /m²)
单位速度NSUnitSpeed米/秒(m / s)
单位温度NSUnitTemperature开尔文(K)
单位体积NSUnitVolume升(L)

3.2 字节转换

@interface NSByteCountFormatter : NSFormatter 

- (void)testNSByteCountFormatter{
    
    
    NSByteCountFormatter *format = [[NSByteCountFormatter alloc] init];
     //以MB输出
    format.allowedUnits = NSByteCountFormatterUseMB;
    //1024字节为1KB
    format.countStyle = NSByteCountFormatterCountStyleBinary;
    // 输出结果显示单位
    format.includesUnit =  YES;
    // 输出结果显示数据
    format.includesCount = YES;
    //是否显示完整的字节
    format.includesActualByteCount = YES;


    NSString *str = [format stringFromByteCount:1024*1024];
    
    NSLog(@"NSByteCountFormatter: %@",str);// 1 MB (1,048,576 bytes)

    

}

3.3 长度单位

- (void)testNSLengthFormatter{
    
    
    //长度单位
    NSLengthFormatter  *lengthFormatter = [[NSLengthFormatter alloc] init];
    
    [lengthFormatter.numberFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh"]];
    
    lengthFormatter.unitStyle = NSFormattingUnitStyleLong;
    /// 输出 200米
    NSString *lengthOutputString1 = [lengthFormatter stringFromValue:200 unit:NSLengthFormatterUnitMeter];
    NSLog(@" 输出 NSLengthFormatterUnitMeter: %@",lengthOutputString1);

    /// 输出 30米
    NSString *lengthOutputString2 = [lengthFormatter stringFromMeters:30];

    NSLog(@" 输出 stringFromMeters: %@",lengthOutputString2);

    /// 输出 meters
    NSString *lengthOutputString3 = [lengthFormatter unitStringFromValue:33333.2 unit:NSLengthFormatterUnitMeter];
    NSLog(@" 输出 NSLengthFormatterUnitMeter: %@",lengthOutputString3);
}

3.4 能量格式化

- (void)NSEnergyFormatter

{
    
    //能量格式化(卡cal)
    NSEnergyFormatter *formatter = [[NSEnergyFormatter alloc] init];
    formatter.forFoodEnergyUse = YES;
    
    [formatter.numberFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];

    NSString *outputString = [formatter stringFromJoules:1000.0];
    NSLog(@" 输出 stringFromJoules: %@",outputString);//1,000焦耳

    

}

3.5 质量格式化

- (void)testNSMassFormatter{
    
    //质量格式化
    NSMassFormatter *massFormatter = [[NSMassFormatter alloc] init];
    [massFormatter.numberFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
    massFormatter.unitStyle = NSFormattingUnitStyleLong;
    /// 输出 200克
    NSString *outputString1 = [massFormatter stringFromValue:200 unit:NSMassFormatterUnitGram];
    NSLog(@" 输出 NSMassFormatterUnitGram: %@",outputString1);

    /// 输出 200千克
    NSString *outputString2 = [massFormatter stringFromKilograms:200];
    NSLog(@" 输出 stringFromKilograms: %@",outputString2);

    /// 输出 kilograms
    NSString *outputString3 = [massFormatter unitStringFromValue:1111 unit:NSMassFormatterUnitKilogram];
    
    NSLog(@" 输出 NSMassFormatterUnitKilogram: %@",outputString3);

    

}

V 名片格式化

名片对象和名片格式化字符串的快速转换,最核心的还是在于locale属性对名片信息进行本地化(根据不同的语言环境进行格式化)。

/* Specifies the locale to format names. Defaults to autoupdatingCurrentLocale. Also resets to autoupdatingCurrentLocale on assignment of nil.
 */
@property (null_resettable, copy) NSLocale *locale API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0));

[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh"]];

  1. personNameComponentsFromString:
/**
 NSPersonNameComponents
>An object that manages the separate parts of a person's name to allow locale-aware formatting.

*/
//通过固定格式的字符串快速创建名片信息:@"Dr. Gregory John Casamento PhD"
void runTests()
{

    NSPersonNameComponents *pnc = [[NSPersonNameComponents alloc] init];
    [pnc setGivenName: @"Gregory"];
    [pnc setMiddleName: @"John"];
    [pnc setFamilyName: @"Casamento"];
    [pnc setNameSuffix: @"PhD"];
    [pnc setNamePrefix: @"Dr."];

NSPersonNameComponents *pnc2 = [fmt personNameComponentsFromString:
                                    @"Dr. Gregory John Casamento PhD"];

    passTest([[pnc givenName] isEqualToString:
              [pnc2 givenName]], @"First name matches");
    passTest([[pnc middleName] isEqualToString:
              [pnc2 middleName]], @"Middle name matches");
    passTest([[pnc familyName] isEqualToString:
              [pnc2 familyName]], @"Family name matches");
    passTest([[pnc nameSuffix] isEqualToString:
              [pnc2 nameSuffix]], @"Suffix name matches");
    passTest([[pnc namePrefix] isEqualToString:
              [pnc2 namePrefix]], @"Prefix name matches");


}
/* Show whether test was passed */
void passTest(BOOL flag,
              NSString *msg)
{
    if(flag == YES)
    {
        NSLog(@"PASS: %@",msg);
    }
    else
    {
        NSLog(@"FAIL: %@",msg);
    }
}


  1. stringFromPersonNameComponents:
//NSPersonNameComponentsFormatter

//@interface NSPersonNameComponentsFormatter : NSFormatter 


    NSPersonNameComponentsFormatter *formatter = [[NSPersonNameComponentsFormatter alloc] init];
    NSPersonNameComponents *p = [[NSPersonNameComponents alloc] init];
    p.givenName = @"名字";
    p.familyName = @"姓";
    p.nameSuffix = @"后缀";
    p.namePrefix = @"前缀";
    p.nickname = @"昵称";
    p.middleName = @"中间符号";
    NSString *outputString1 =[formatter stringFromPersonNameComponents:p];
    formatter.style = NSPersonNameComponentsFormatterStyleLong;


typedef NS_ENUM(NSInteger, NSPersonNameComponentsFormatterStyle) {
    NSPersonNameComponentsFormatterStyleDefault = 0,

    /* Relies on user preferences and language defaults to display shortened form appropriate
      for display in space-constrained settings, e.g. C Darwin */
    NSPersonNameComponentsFormatterStyleShort,

    /* The minimally necessary features for differentiation in a casual setting , e.g. Charles Darwin */
    NSPersonNameComponentsFormatterStyleMedium,

    /* The fully-qualified name complete with all known components, e.g. Charles Robert Darwin, FRS */
    NSPersonNameComponentsFormatterStyleLong,

    /* The maximally-abbreviated form of a name suitable for monograms, e.g. CRD) */
    NSPersonNameComponentsFormatterStyleAbbreviated
} API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0));

*/

see also

iOS处理语言工具CFStringTransform : 智能地处理用户的输入内容,经典应用场景【索引】

通讯录demo源码:https://download.csdn.net/download/u011018979/19088189 1、原理:通过对用户输入内容,利用CFStringTransform变换,可以轻松实现实现一个通用的搜索index 2、 特色:搜索内容可以是多语言的 3、文章:https://kunnan.blog.csdn.net/article/details/109603377