iOS小技能:金额格式处理 (货币符号本地化)
原创
©著作权归作者所有:来自51CTO博客作者#公众号:iOS逆向的原创作品,请联系作者获取转载授权,否则将追究法律责任
引言
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
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
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]];
风格
| 对应的枚举
| 输出样式
|
四舍五入的整数
| NSNumberFormatterNoStyle
| 12346
|
小数形式
| NSNumberFormatterDecimalStyle
| 12,345.678
|
货币形式(已本地化处理)
| NSNumberFormatterCurrencyStyle
| $12,345.68
|
百分数形式
| NSNumberFormatterPercentStyle
| 1,234,568%
|
科学计数
| NSNumberFormatterScientificStyle
| 1.2345678E4
|
朗读形式
| NSNumberFormatterSpellOutStyle
| twelve thousand three hundred forty-five point six seven eight
|
序数形式
| NSNumberFormatterOrdinalStyle
| 12,346th
|
货币形式(已本地化处理)
| NSNumberFormatterCurrencyISOCodeStyle
| USD12,345.68
|
货币形式(已本地化处理)
| NSNumberFormatterCurrencyPluralStyle
| 12,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
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
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;
// 四色五入方式
II 时间格式化(NSDateFormatter)
@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)。缩写 Z2.1 系统自带的样式
date and time format styles
typedef NS_ENUM(NSUInteger, NSDateFormatterStyle) { // NSDateFormatterNoStyle = kCFDateFormatterNoStyle,
NSDateFormatterShortStyle = kCFDateFormatterShortStyle,
NSDateFormatterMediumStyle = kCFDateFormatterMediumStyle,
NSDateFormatterLongStyle = kCFDateFormatterLongStyle,
NSDateFormatterFullStyle格式
| 日期
| 时间
|
NSDateFormatterNoStyle
| ""
| ""
|
NSDateFormatterShortStyle
| 2022/7/31
| 上午11:40
|
NSDateFormatterMediumStyle
| 2022年7月31日
| 上午11:40:29
|
NSDateFormatterLongStyle
| 2022年7月31日
| GMT+8 上午11:40:49
|
NSDateFormatterFullStyle
| 2022年7月31日 星期三
| 中国标准时间 上午11:41:16
|
2.2 自定义日期格式化
- 案例1: 小程序订单小票
- 案例2:订单详情时间格式化
setDateFormat
- stringFromDate:
- 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];
returnIII 数量单位格式化
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
列表
| 对应类
| 基础单位
|
加速度单位
| NSUnitAcceleration
| m /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"]];
-
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);
}
}
-
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 : 智能地处理用户的输入内容,经典应用场景【索引】
1、原理:通过对用户输入内容,利用CFStringTransform变换,可以轻松实现实现一个通用的搜索index
2、 特色:搜索内容可以是多语言的