源码地址:https://github.com/csfuwwc/NSNumberFormatterTest
2020.05.20更新
新增支持0开头银行卡号
2018.11.30更新
现在好像已经有最多23位银行卡号了?使用的同学记得核准业务涉及银行卡号长度哈
2018.09.05更新
在将string转为number时使用NSDecimalNumber类型,可有效避免精度损失情况
2018.01.18更新
NSString+More 新增<已有数据展示时格式化>
//转换为手机号格式 xxx xxxx xxxx
- (NSString *)phoneFormatter;
//转换为银行卡格式 xxxx xxxx xxxx xxxx xxx
- (NSString *)banCardFormatter;
位数不够时也显示上述格式,
如1391111111 显示为 139 1111 111
如622848040256489001显示为6228 4804 0256 4890 01
UITextField+More 新增<输入数据时格式化显示>
//格式-手机号/银行卡/金额等等
@property (assign, nonatomic)UIInputTextFieldStyle style;
//最大输入位数
@property (assign, nonatomic)NSInteger maxInputLength;
//最终字符
@property (assign, nonatomic)NSString * resultString;
style:控制格式,目前支持手机号/银行卡 后期将扩展支持小数位数自定义(如小数点后指定位数,有其他需求的童鞋可以留言~~~)
maxInputLength:控制位数,当超过指定位数时不可再输入
resultString:最终字符,主要针对手机号/银行卡格式输入控制时获取实际字符
原文
场景一、手机号/银行卡 格式化<展示>
核心代码
- (NSString *)PhoneFormatter:(NSString*)str
{
NSDecimalNumber * number = [[NSDecimalNumber alloc] initWithString:str]
NSNumberFormatter * formatter = [NSNumberFormatter new];
//设置分隔符
[formatter setGroupingSeparator:@" "];
//设置分割格式
formatter.positiveFormat = @"###,###0";
//如果string以0开头
if ([self hasPrefix:@"0"] && [number stringValue].length != self.length)
{
NSString *prefixStr = [self substringToIndex:[self length]-[number stringValue].length];
NSMutableString *tempStr = [prefixStr mutableCopy];
for (NSInteger i = 4; i <= prefixStr.length; i += 4)
{
[tempStr insertString:@" " atIndex:(i+(i-1)/4)];
}
formatter.positivePrefix = tempStr;
}
NSString * string = [formatter stringFromNumber:number];
NSLog(@"%@",string);
}
输入手机号 13911112222 输出结果如下:
139 1111 2222
同理,输入一个银行卡号 6228480402564890018 输出结果如下:
622 8480 4025 6489 0018
适用场景:已有数据,格式化展示。
场景二、手机号/银行卡 格式化<输入时>
如果继续使用上面方法,输入过程中数字跳动,逼死强迫症。有兴趣的同学可以试试。
核心代码
NSDecimalNumber * number = [[NSDecimalNumber alloc] initWithString:string];
NSNumberFormatter * formatter = [NSNumberFormatter new];
//设置分隔符
[formatter setGroupingSeparator:@" "];
//设置使用组分割
formatter.usesGroupingSeparator = YES;
// 数字分割的尺寸<从右向左>
formatter.groupingSize = ([string length]-3)%4>0?([string length]-3)%4:4;
//除了groupingSize决定的尺寸外,其他数字位分割的尺寸
formatter.secondaryGroupingSize = [string length]>7?4:3;
//如果string以0开头
if ([string hasPrefix:@"0"] && [number stringValue].length != string.length)
{
NSString *prefixStr = [string substringToIndex:[string length]-[number stringValue].length];
NSMutableString *tempStr = [prefixStr mutableCopy];
for (NSInteger i = 4; i <= prefixStr.length; i += 4)
{
[tempStr insertString:@" " atIndex:(i+(i-1)/4)];
}
formatter.positivePrefix = tempStr;
}
//获取格式化后的字符
tf.text = [formatter stringFromNumber:number];
适用场景:输入字符同时要求格式。
封装集成
在项目中,通过封装TextField+More分类,使用时,只需要一句代码即可实现:
self.inputTextField.style = UIInputTextFieldStyle_Phone;
下面看下TextField+More的实现
<UITextField+More.h>
// UITextField+More.h
// NSNumberFormatterTest
//
// Created by 李彦鹏 on 2017/12/7.
// Copyright © 2017年 csfuwwc. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef void(^EditBlock)(UITextField * tf);
typedef enum : NSUInteger {
UIInputTextFieldStyle_None = 0,//无格式限制
UIInputTextFieldStyle_Phone = 1, //手机号
UIInputTextFieldStyle_BankCard = 2, //银行卡
} UIInputTextFieldStyle;
@interface UITextField (More)<UITextFieldDelegate>
//扩展输入框style属性,使用时直接赋值style即可实现格式化功能
@property (assign, nonatomic)UIInputTextFieldStyle style;
//最大输入位数
@property (assign, nonatomic)NSInteger maxInputLength;
//最终字符
@property (assign, nonatomic)NSString * resultString;
/**
* 输入框事件触发回调
*
* @param event 事件
* @param block 回调
*/
- (void)handleControlEvent:(UIControlEvents)event withBlock:(EditBlock)block;
<UITextField+More.m>
//
// UITextField+More.m
// NSNumberFormatterTest
//
// Created by 李彦鹏 on 2017/12/7.
// Copyright © 2017年 csfuwwc. All rights reserved.
//
#import "UITextField+More.h"
#import <objc/runtime.h>
@implementation UITextField (More)
//设置最大输入位数
#pragma mark - UITextFieldInputLength
static const char * TextFieldMaxInputLengthKey = "TextFieldMaxInputLengthKey";
- (void)setMaxInputLength:(NSInteger)maxInputLength
{
objc_setAssociatedObject(self, TextFieldMaxInputLengthKey, @(maxInputLength), OBJC_ASSOCIATION_ASSIGN);
self.delegate = self;
}
- (NSInteger)maxInputLength
{
return [objc_getAssociatedObject(self, TextFieldMaxInputLengthKey) integerValue];
}
#pragma mark - UIControlEventBlock 输入字符Block回调实现
static const char * TextFieldMoreKey = "TextFieldMoreKey";
-(void)handleControlEvent:(UIControlEvents)event withBlock:(EditBlock)block
{
objc_setAssociatedObject(self, TextFieldMoreKey, block, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self addTarget:self action:@selector(editEvent:) forControlEvents:event];
}
-(void)editEvent:(UITextField *)textField
{
EditBlock block = objc_getAssociatedObject(self, TextFieldMoreKey);
if (block)
{
block(textField);
}
}
#pragma mark - UITextFieldInputSytle 输入字符格式化核心部分
static const char * TextFieldStyleKey = "TextFieldStyleKey";
- (void)setStyle:(UIInputTextFieldStyle)style
{
objc_setAssociatedObject(self, TextFieldStyleKey, @(style), OBJC_ASSOCIATION_ASSIGN);
switch (style)
{
case UIInputTextFieldStyle_Phone:
{
//手机号码最多11位
self.maxInputLength = 11;
//检测输入-格式化
[self formatterInputString];
}
break;
case UIInputTextFieldStyle_BankCard:
{
//银行卡号最多19位
self.maxInputLength = 19;
//检测输入-格式化
[self formatterInputString];
}
break;
default:
{
//默认不限制位数
self.maxInputLength = MAXFLOAT;
}
break;
}
}
- (UIInputTextFieldStyle)style
{
return [objc_getAssociatedObject(self, TextFieldStyleKey) integerValue];
}
//格式化输入字符
- (void)formatterInputString
{
[self handleControlEvent:UIControlEventEditingChanged withBlock:^(UITextField *tf) {
//去空
NSString * string = [tf.text stringByReplacingOccurrencesOfString:@" " withString:@""];
if ([string length]==0)
{
return;
}
NSDecimalNumber * number = [[NSDecimalNumber alloc] initWithString:string];
//获取格式化后的字符
tf.text = [[self formatterWithString:string] stringFromNumber:number];
}];
}
- (NSNumberFormatter *)formatterWithString:(NSString *)string
{
NSNumberFormatter * formatter = [NSNumberFormatter new];
//设置分隔符
[formatter setGroupingSeparator:@" "];
//设置使用组分割
formatter.usesGroupingSeparator = YES;
switch (self.style)
{
case UIInputTextFieldStyle_Phone:
{
//设置首个组长度<从右向左>
formatter.groupingSize = ([string length]-3)%4>0?([string length]-3)%4:4;
//设置第二个组长度
formatter.secondaryGroupingSize = [string length]>7?4:3;
}
break;
case UIInputTextFieldStyle_BankCard:
{
//设置首个组长度<从右向左>
formatter.groupingSize = ([string length]-4)%4>0?([string length]-4)%4:4;
//设置第二个组长度
formatter.secondaryGroupingSize = 4;
}
break;
default:
break;
}
return formatter;
}
#pragma mark - UITextFieldDelegate
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (![string isEqualToString:@""])
{
NSString * currentString = self.style!=UIInputTextFieldStyle_None?[textField.text stringByReplacingOccurrencesOfString:@" " withString:@""]:textField.text;
if ([currentString length]>= self.maxInputLength)
{
return NO;
}
}
return YES;
}
//最终字符
- (NSString *)resultString
{
if (self.style != UIInputTextFieldStyle_None)
{
return [self.text stringByReplacingOccurrencesOfString:@" " withString:@""];
}
return self.text;
}
@end
源码地址:https://github.com/csfuwwc/NSNumberFormatterTest
结束语
更多格式
http://unicode.org/reports/tr35/tr35-6.html#Number_Format_Patterns
PS:NSNumberFormatter远比想象的强大哟!
谢谢大家。