iOS开发之UITextField的文本格式扩展

     在开发的过程中,为了使产品美观,和数据易读。我们经常会接到这样的需求,比如:在用户输入手机号码的地方自动空格,在TextField框里面自动生成手机号码的格式, 类似与这样的需求还有身份证格式和银行卡格式!

     这个需求的难点在于,在输入的时候在合适的位置添加空格和在删除的时候也一并把空格删除掉!

     在这里我写了一个UITextField的分类,来实现手机号;银行卡,以及身份证号码输入的时候进行格式化:

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, HBTextFieldFormatType) {
    kHBTextFieldTypeFormatUnkown = 0, // 未知
    kHBTextFieldTypeFormatBankCard,   // 银行卡号格式
    kHBTextFieldTypeFormatPhoneNO,    // 手机号码格式
    kHBTextFieldTypeFormatIDNO,       // 身份证号码格式
};
@interface UITextField (Format)

@property (nonatomic, assign) HBTextFieldFormatType textFormatType;


@end

    .m文件的实现:

#import "UITextField+Format.h"
#import <objc/runtime.h>

static NSString *formatType = @"formatType";

@implementation UITextField (Format)
@dynamic textFormatType;

- (void)setTextFormatType:(HBTextFieldFormatType)textFormatType{
    objc_setAssociatedObject(self,&formatType,@(textFormatType),OBJC_ASSOCIATION_COPY);
    
    [self addTarget:self action:@selector(reformatAsBankNumber:) forControlEvents:UIControlEventEditingChanged];
}

- (HBTextFieldFormatType )textFormatType{
    NSString *textFormatType = (NSString *)objc_getAssociatedObject(self, &formatType);
    return [textFormatType integerValue];
}


-(void)reformatAsBankNumber:(UITextField *)textField {
    
    /**
     *  判断正确的光标位置
     */
    NSUInteger targetCursorPostion = [textField offsetFromPosition:textField.beginningOfDocument toPosition:textField.selectedTextRange.start];
    NSString *numberWithoutSpaces = [self removeNonDigits:textField.text andPreserveCursorPosition:&targetCursorPostion];
    
    NSString *numberWithSpaces;
    if(self.textFormatType == kHBTextFieldTypeFormatBankCard){
        numberWithSpaces = [self insertSpacesEveryFourDigitsIntoString:numberWithoutSpaces andPreserveCursorPosition:&targetCursorPostion];
    }else if (self.textFormatType == kHBTextFieldTypeFormatPhoneNO){
        numberWithSpaces = [self insertSpacesIntoPhoneNumberString:numberWithoutSpaces andPreserveCursorPosition:&targetCursorPostion];
    }else if (self.textFormatType == kHBTextFieldTypeFormatIDNO){
        numberWithSpaces = [self insertSpacesIntoIDNOString:numberWithoutSpaces andPreserveCursorPosition:&targetCursorPostion];
    }
    
    textField.text = numberWithSpaces;
    UITextPosition *targetPostion = [textField positionFromPosition:textField.beginningOfDocument offset:targetCursorPostion];
    [textField setSelectedTextRange:[textField textRangeFromPosition:targetPostion toPosition:targetPostion]];
}

/**
 *  除去非数字字符,确定光标正确位置
 *
 *  @param string         当前的string
 *  @param cursorPosition 光标位置
 *
 *  @return 处理过后的string
 */
- (NSString *)removeNonDigits:(NSString *)string andPreserveCursorPosition:(NSUInteger *)cursorPosition {
    NSUInteger originalCursorPosition =*cursorPosition;
    NSMutableString *digitsOnlyString = [NSMutableString new];
    
    for (NSUInteger i=0; i<string.length; i++) {
        unichar characterToAdd = [string characterAtIndex:i];
        
        if(isdigit(characterToAdd)) {
            NSString *stringToAdd = [NSString stringWithCharacters:&characterToAdd length:1];
            [digitsOnlyString appendString:stringToAdd];
        }
        else {
            if(i<originalCursorPosition) {
                (*cursorPosition)--;
            }
        }
    }
    return digitsOnlyString;
    
}

#pragma 银行卡格式
/**
 *  将空格插入我们现在的string 中,并确定我们光标的正确位置,防止在空格中
 *
 *  @param string         当前的string
 *  @param cursorPosition 光标位置
 *
 *  @return 处理后有空格的string
 */
- (NSString *)insertSpacesEveryFourDigitsIntoString:(NSString *)string andPreserveCursorPosition:(NSUInteger *)cursorPosition{
    NSMutableString *stringWithAddedSpaces = [NSMutableString new];
    NSUInteger cursorPositionInSpacelessString = *cursorPosition;
    
    for (NSUInteger i=0; i<string.length; i++) {
        if(i>0)
        {
            if(i%4 == 0) {
                [stringWithAddedSpaces appendString:@" "];
                
                if(i<cursorPositionInSpacelessString) {
                    (*cursorPosition)++;
                }
            }
        }
        
        unichar characterToAdd = [string characterAtIndex:i];
        NSString *stringToAdd = [NSString stringWithCharacters:&characterToAdd length:1];
        [stringWithAddedSpaces appendString:stringToAdd];
    }
    return stringWithAddedSpaces;
}

#pragma 手机号码格式
- (NSString *)insertSpacesIntoPhoneNumberString:(NSString *)string andPreserveCursorPosition:(NSUInteger *)cursorPosition{
    NSMutableString *stringWithAddedSpaces = [NSMutableString new];
    NSUInteger cursorPositionInSpacelessString = *cursorPosition;
    
    for (NSUInteger i=0; i<string.length; i++) {
        if(i>0)
        {
            if(i == 3 || i == 7) {
                [stringWithAddedSpaces appendString:@" "];
                
                if(i<cursorPositionInSpacelessString) {
                    (*cursorPosition)++;
                }
            }
        }
        
        unichar characterToAdd = [string characterAtIndex:i];
        NSString *stringToAdd = [NSString stringWithCharacters:&characterToAdd length:1];
        [stringWithAddedSpaces appendString:stringToAdd];
    }
    return stringWithAddedSpaces;
}

#pragma 身份证格式
- (NSString *)insertSpacesIntoIDNOString:(NSString *)string andPreserveCursorPosition:(NSUInteger *)cursorPosition{
    NSMutableString *stringWithAddedSpaces = [NSMutableString new];
    NSUInteger cursorPositionInSpacelessString = *cursorPosition;
    
    for (NSUInteger i=0; i<string.length; i++) {
        if(i>0)
        {
            if(i == 6 || i == 10 || i == 14) {
                [stringWithAddedSpaces appendString:@" "];
                
                if(i<cursorPositionInSpacelessString) {
                    (*cursorPosition)++;
                }
            }
        }
        
        unichar characterToAdd = [string characterAtIndex:i];
        NSString *stringToAdd = [NSString stringWithCharacters:&characterToAdd length:1];
        [stringWithAddedSpaces appendString:stringToAdd];
    }
    return stringWithAddedSpaces;
}


@end

       这里需要注意的是OC的分类允许给分类添加属性,但不会自动生成getter、setter方法,所以我们必须自己实现他的 getter、setter,但是要通过运行时建立关联引用!  我们这个类实现也正是利用OC的这个特征,在重写 setter方法的时机给UITextField文本格式的实现提供了入口!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值