概述
在有些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:@"0123456789b"];
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;
}
最后
以上就是忧郁戒指为你收集整理的iOS开发:编辑框格式化输入、删除、插入预览思路源代码下载的全部内容,希望文章能够帮你解决iOS开发:编辑框格式化输入、删除、插入预览思路源代码下载所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复