UITextField加间隔符号格式化

在输入框中输入手机号码/电话号码/银行卡号/身份证号时经常需要格式化显示,用户体验更好.

网上解决方法很多,找了不少但也是不太适合,于是把其中一些修改成以下方法,在UITextField的分类中添加过滤,浸入性小,耦合性小,用起来还是很方便的.间隔符号可以自定义,过滤条件也可以自己增加和修改,如只能输入数字和X(身份证号)等限制.

直接上代码:

UITextField的分类:

UITextField+Extension.h

#import <UIKit/UIKit.h>
// 准许输入字符类型
typedef NS_ENUM(NSInteger,CharsType) {
    CharsType_numeral = 1,// 只许数字
    CharsType_letter,// 只许大小写字母
    CharsType_numeralAndXx,// 只许数字加上X和x
    CharsType_numeralAndLetter,// 只许数字加上大小写字母
    CharsType_allChar,// 允许输入所有字符
};

@interface UITextField (Extension)

/**
 *  格式化输入的文字
 *
 *  @param textField 正在输入的textField
 *  @param range     输入字符的位置
 *  @param string    输入的字符
 *  @param CharType  准许输入字符类型
 *  @param maxLength 限制输入文字的最大长度
 *  @param indexs    插入分隔符的位置下标数组
 *  @param separator 插入的分隔符号
 *
 *  @return 是否加显示到textField输入框内
 */
+ (BOOL)textField:(UITextField *)textField range:(NSRange)range string:(NSString *)string CharType:(CharsType)CharType maxLength:(NSInteger)maxLength separatorIndexs:(NSArray *)indexs separator:(NSString *)separator;

@end

UITextField+Extension.m

#import "UITextField+Extension.h"

@implementation UITextField (Extension)

+ (BOOL)textField:(UITextField *)textField range:(NSRange)range string:(NSString *)string CharType:(CharsType)CharType maxLength:(NSInteger)maxLength separatorIndexs:(NSArray *)indexs separator:(NSString *)separator {
    
    if ([string isEqualToString:separator]) return NO;
    
    // 添加限制条件,只能输入这个字符串内的字符
    NSString *allowChar;
    switch (CharType) {
        case CharsType_numeral:
            allowChar = @"0123456789\b";
            break;
        case CharsType_letter:
            allowChar = @"qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM\b";
            break;
        case CharsType_numeralAndXx:
            allowChar = @"0123456789Xx\b";
            break;
        case CharsType_numeralAndLetter:
            allowChar = @"0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM\b";
            break;
        default:
            break;
    }
    
    NSCharacterSet *characterSet;
    if (CharType != CharsType_allChar) {
        characterSet = [NSCharacterSet characterSetWithCharactersInString:allowChar];
        string = [string stringByReplacingOccurrencesOfString:separator withString:@""];
        if ([string rangeOfCharacterFromSet:[characterSet invertedSet]].location != NSNotFound) {
            return NO;
        }
    }
    
    NSString *text = textField.text;
    
    if ([string isEqualToString:@""]){
        if (range.length == 1) {
            if (range.location == text.length - 1) {
                if ([[text substringFromIndex:text.length -1] isEqualToString:separator]) {
                    [textField deleteBackward];
                }
                return YES;
            }
            else {
                NSInteger offset = range.location;
                if (range.location < text.length && [[text substringFromIndex:range.location] isEqualToString:separator] && [textField.selectedTextRange isEmpty]) {
                    [textField deleteBackward];
                    offset --;
                }
                [textField deleteBackward];
                textField.text = [self parseString:textField.text separatorIndexs:indexs separator:separator];
                UITextPosition *newPos = [textField positionFromPosition:textField.beginningOfDocument offset:offset];
                textField.selectedTextRange = [textField textRangeFromPosition:newPos toPosition:newPos];
                return NO;
            }
        }
        else if (range.length > 1) {
            BOOL isLast = NO;
            if(range.location + range.length == textField.text.length ){
                isLast = YES;
            }
            [textField deleteBackward];
            textField.text = [self parseString:textField.text separatorIndexs:indexs separator:separator];
            
            __block NSInteger offset = range.location;
            [indexs enumerateObjectsUsingBlock:^(id  _Nonnull obj,NSUInteger idx,BOOL * _Nonnull stop) {
                NSInteger index = [obj integerValue];
                if (range.location == index) offset++;
            }];
            
            if (isLast) {
            } else {
                UITextPosition *newPos = [textField positionFromPosition:textField.beginningOfDocument offset:offset];
                textField.selectedTextRange = [textField textRangeFromPosition:newPos toPosition:newPos];
            }
            return NO;
        }
        else {
            return YES;
        }
    }
    else if (string.length > 0) {
        NSString *str;
        if (CharType != CharsType_allChar) {
            str = [textField.text stringByTrimmingCharactersInSet:[characterSet invertedSet]];
        }
        str = [textField.text stringByReplacingOccurrencesOfString:separator withString:@""];
        
        if ((str.length + string.length - range.length > maxLength) ) {
            return NO;
        }
        
        [textField insertText:string];
        textField.text = [self parseString:textField.text separatorIndexs:indexs separator:separator];
        
        __block NSInteger offset = range.location + string.length;
        [indexs enumerateObjectsUsingBlock:^(id  _Nonnull obj,BOOL * _Nonnull stop) {
            NSInteger index = [obj integerValue];
            if (range.location == index) offset++;
        }];
        UITextPosition *newPos = [textField positionFromPosition:textField.beginningOfDocument offset:offset];
        textField.selectedTextRange = [textField textRangeFromPosition:newPos toPosition:newPos];
        return NO;
    } else {
        return YES;
    }
}

+ (NSString *)parseString:(NSString*)string separatorIndexs:(NSArray *)indexs separator:(NSString *)separator {
    if (!string) return nil;
    NSMutableString *mStr = [NSMutableString stringWithString:[string stringByReplacingOccurrencesOfString:separator withString:@""]];
    [indexs enumerateObjectsUsingBlock:^(id  _Nonnull obj,BOOL * _Nonnull stop) {
        NSInteger index = [obj integerValue];
        if (mStr.length > index) [mStr insertString:separator atIndex:index];
    }];
    return  mStr;
}

@end

使用:

#import "ViewController.h"
#import "UITextField+Extension.h"

@interface ViewController () <UITextFieldDelegate>
@property (weak,nonatomic) IBOutlet UITextField *tf_phone;
@property (weak,nonatomic) IBOutlet UITextField *tf_idCard;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _tf_phone.delegate = self;
    _tf_idCard.delegate = self;
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField == _tf_phone) {
        return [UITextField textField:textField range:range string:string CharType:CharsType_numeral maxLength:11 separatorIndexs:@[@(3),@(8)] separator:@"-"];
    } else if (textField == _tf_idCard) {
        return [UITextField textField:textField range:range string:string CharType:CharsType_numeralAndXx maxLength:18 separatorIndexs:@[@(6),@(11),@(16)] separator:@" "];
    }
    return YES;
}

@end

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...