一句代码实现银行卡手机号输入时格式化

源码地址: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];
一句代码实现银行卡手机号输入时格式化_第1张图片
formatter.gif

适用场景:输入字符同时要求格式。

封装集成

在项目中,通过封装TextField+More分类,使用时,只需要一句代码即可实现:

self.inputTextField.style = UIInputTextFieldStyle_Phone;

下面看下TextField+More的实现



//  UITextField+More.h
//  NSNumberFormatterTest
//
//  Created by 李彦鹏 on 2017/12/7.
//  Copyright © 2017年 csfuwwc. All rights reserved.
//

#import 

typedef void(^EditBlock)(UITextField * tf);

typedef enum : NSUInteger {

     UIInputTextFieldStyle_None = 0,//无格式限制

     UIInputTextFieldStyle_Phone = 1, //手机号

     UIInputTextFieldStyle_BankCard = 2, //银行卡

} UIInputTextFieldStyle;

@interface UITextField (More)


//扩展输入框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
//  NSNumberFormatterTest
//
//  Created by 李彦鹏 on 2017/12/7.
//  Copyright © 2017年 csfuwwc. All rights reserved.
//
  
#import "UITextField+More.h"
#import 

@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远比想象的强大哟!

谢谢大家。

你可能感兴趣的:(一句代码实现银行卡手机号输入时格式化)