您的位置:首页 > 移动开发 > IOS开发

iOS开发:编辑框格式化输入、删除、插入

2016-06-12 10:14 239 查看
在有些iOS app中需要用到textfield格式化输入、删除、插入,比如银行卡号6215 8888 8888 8888 888等要求4位一分格(手机号同理),如何在编辑框输入和删除时自动显示这样的效果呢,本文有个实现思路。

预览



思路

重写编辑框的委托函数在里面进行实时监控编辑框内容的变化
每次字符编辑后用一个特定的函数对字符串格式化再显示和提交
考虑了从中间插入和删除的情况,以及复制粘贴编辑的情况
限制输入其他字符以及字符个数
添加银行卡号校验规则

实现编辑框委托函数
//do the formatting while textfield text is changing
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{

//only receive number and backspace input, in case some numberPad receive non-number chars such as sougou T_T
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789\b"];
NSString *checkStr = [self noneSpaseString:string];
if ([checkStr rangeOfCharacterFromSet:[characterSet invertedSet]].location != NSNotFound)
return NO;

//process the textField text
NSString* text = textField.text;
//delete
if([string length] <= 0) // or [string isEqualToString:'']
{

NSLog(@"slected range: location %d, length %d", range.location, range.length);

//delete the last char
if(range.location == text.length - 1) //because already delete one char, so it is text.length - 1
{
//actually it will delete twice, first the backspace then delete the space
if(text.length >=2 && [text characterAtIndex:text.length-2] == ' ')
[textField deleteBackward];

return YES;
}
//delete in the middle
else
{
NSInteger offset = range.location;

NSLog(@"seleted textrange %@", textField.selectedTextRange);

if(range.location < text.length && [text characterAtIndex:range.location - 1] == ' ' /*&& [textField.selectedTextRange isEmpty]*/)
{
[textField deleteBackward]; //Remove the character just before the cursor and redisplay the text.
offset--;
}
[textField deleteBackward];

//format the  string
textField.text = [self parseString:textField.text];

//reset the cursor pos
UITextPosition *newPos = [textField positionFromPosition:textField.beginningOfDocument offset:offset];
textField.selectedTextRange = [textField textRangeFromPosition:newPos toPosition:newPos];

return NO;
}
}
//insert int tail or in the middle
else
{

//limit the number of digits
//consider the paste and replace several charcters at one time,ex: 135169 -> 14169, that is:6 + 1 - 2 <19
if([self noneSpaseString:textField.text].length + string.length - range.length > 19)
{
NSLog(@"text len: %d, string len: %d, range len: %d", [self noneSpaseString:textField.text].length,
string.length, range.length);
return NO;
}

[textField insertText:string]; //Add the character text to the cursor and redisplay the text.

//format the string
textField.text = [self parseString:textField.text];

//move the cursor to the right place
NSInteger offset = range.location + string.length;
if(range.location == 4 ||
range.location  == 9 ||
range.location == 14 ||
range.location == 19)
offset++;

//reset the cursor pos
UITextPosition *newPos = [textField positionFromPosition:textField.beginningOfDocument offset:offset];
textField.selectedTextRange = [textField textRangeFromPosition:newPos toPosition:newPos];
return NO;
}

return NO;
}

每次字符输入、删除插入过程中,频繁的使用格式化字符串函数,注意如果是在中间插入和删除字符,则需要对光标进行重新定位,另外,这个函数的return值有时候要返回NO,因为这里手动处理了显示的字符串,所以有时候编辑框的编辑动作不要提交给系统,以免重复处理。

格式化字符串
//remove the space of string
-(NSString*)noneSpaseString:(NSString*)string
{
return [string stringByReplacingOccurrencesOfString:@" " withString:@""];
}

//everytime check the textfield string to format
- (NSString*)parseString:(NSString*)textStr
{
if (!textStr) {
return nil;
}
NSMutableString *formatTextStr = [NSMutableString stringWithString:[textStr stringByReplacingOccurrencesOfString:@" " withString:@""]];

//insert space in step by step,ex: 123456789015 -> 1234 56789015 -> 1234 5678 9015
if(formatTextStr.length > 4)
[formatTextStr insertString:@" " atIndex:4];
if(formatTextStr.length > 9)
[formatTextStr insertString:@" " atIndex:9];
if(formatTextStr.length > 14)
[formatTextStr insertString:@" " atIndex:14];
if(formatTextStr.length > 19)
[formatTextStr insertString:@" " atIndex:19];

return  formatTextStr;
}


银行卡校验
Luhn算法:https://en.wikipedia.org/wiki/Luhn_algorithm

//check whether the bankcard is valid using the Luhn algorithm
- (BOOL)isValidBankCard:(NSString *)bankCardNumber
{
//reverse odd and even sum
int oddSum = 0;
int evenSum = 0;
int Sum = 0;

int len = bankCardNumber.length;
for(int i = 0; i< len;i++)
{
NSString *digitStr = [bankCardNumber substringWithRange:NSMakeRange(len - 1 - i, 1)];
int digitVal = digitStr.intValue;
if(i & 0x01)
{
digitVal *= 2;
if(digitVal>=10)
digitVal -= 9;
oddSum += digitVal;
}
else
evenSum += digitVal;
}

Sum = oddSum + evenSum;

if(Sum % 10 == 0)
return YES;
else
return NO;
}

源代码下载

csdn:银行卡格式化输入
github:BankCardNumberFormat

更新:限制金额输入整数位和小数位
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{

// 正则法限制小数点位数
//    NSString *amountText = textField.text;
//    NSString *regStr = @"^([1-9][\\d]{0,100}|0)(\\.[\\d]{0,1})?$";
//    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regStr];
//    BOOL match = [predicate evaluateWithObject:amountText];
//    if ([string isEqualToString:@""]) return YES;  // 始终允许用户删除
//    NSString *tmpStr = [amountText stringByAppendingString:string];
//    NSString *numStr = [[tmpStr componentsSeparatedByString:@"."] firstObject];
//    NSInteger amount = [numStr integerValue];
//    if (([amountText intValue] == 99999999) && (![string isEqualToString:@""])) return NO;
//    BOOL result = [amountText isEqualToString:@""] ? YES : (match && ((amount <= 99999999) || [string isEqualToString:@"."]));
//    return result;

// 普通法限制小数点位数
int maxIntLen = 8;  // 最大整数位
int maxFloatLen = 2; // 最大小数位
// 获取原始的字符串
NSMutableString *numberText = [NSMutableString stringWithString:textField.text];
if (![string isEqualToString:@""])
{
// 开头不能直接输入小数点
if (numberText.length == 0 && [string isEqualToString:@"."])
{
return NO;
}

// 以0开头不能多于一位
if ([numberText isEqualToString:@"0"] && ![string isEqualToString:@"."])
{
return NO;
}

// 预先插入字符串
[numberText insertString:string atIndex:range.location];

// 处理字符串,看是否符合要求
// 按小数点分割
NSArray *numsArray = [numberText componentsSeparatedByString:@"."];
if (numsArray.count > 2)
{
// 如果小数点多余1个,不符合要求
return NO;
}
else if (numsArray.count == 2)
{
NSString *intPart = numsArray.firstObject;
NSString *floatPart = numsArray.lastObject;

if (intPart.length > maxIntLen || floatPart.length > maxFloatLen)
{
return NO;
}
}
}
// 正常删除
return YES;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: