跪求关注,最近准备离职,想把博客撑上去好找工作,不求喜欢,求关注,谢谢了
最近整理一下之前的代码,实现高度封装和复用
总结一下输入框格式化,方便用户输入和增加用户体验,基本效果如下
用户在输入电话号码的时候自动格式化为123 4567 8901
用户在输入银行卡号的时候自动格式化为1234 1234 1234 1234 123(16-19位)
用户在输入金钱的时候自动判断两位,一个小数点,如123.12
任意限制输入内容的输入框(不在允许输入范围内的东西不显示)
我们本来这些代码是要写在textField的代理方法中.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
通过这个方法,判定输入内容返回YES或者NO来限制是否能够输入进去,但是这样会有一个问题,就是你用一次你得去复制粘贴一次,而且,如果你的页面里输入框较多,那么你得很费劲的去写swich case或者一长串的if else,不仅麻烦,而且显得很low
那么我们想,能不能把方法封装在tf内部,提供一个外部方法让我们调用判断,我们在代理方法里调用一下就行了,但是这样还会出现一个问题就是,我们不得不把代理方法里面UITextField换成你要判断的类,不然就会找不到这个方法,从而报错.
那么我们想到另一个方法来解决这个问题,就是通过类的扩展,去桥接这个方法.
我们知道OC是动态运行时语言,也是一门弱语言,它会在运行时找到对应的类去调用相应的方法,所以,给跟类UITextField添加一个同名的方法,在运行时调用的时候,每个类自己调用自己对应的方法就可以了
方法如下
首先,给textFeld写一个扩展类,在类中声明一个方法,不用写方法的实现,因为用不到
#import <UIKit/UIKit.h>
@interface UITextField (Extension)
// 自定义一个方法,每个自定义封装的TF都实现这个方法就可以了
- (BOOL)valueChangeValueString:(NSString *)string shouldChangeCharactersInRange:(NSRange)range;
@end
剩下的就是每个封装的TF的自定义方法内容了
- 格式化手机号代码
#import "JXHIphoneTF.h"
@implementation JXHIphoneTF
- (BOOL)valueChangeValueString:(NSString *)string shouldChangeCharactersInRange:(NSRange)range
{
NSString *text = self.text;
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789\\b"];
string = [string stringByReplacingOccurrencesOfString:@" " withString:@""];
if ([string rangeOfCharacterFromSet:[characterSet invertedSet]].location != NSNotFound) {
return NO;
}
NSLog(@"%@",NSStringFromRange(range));
text = [text stringByReplacingCharactersInRange:range withString:string];
text = [text stringByReplacingOccurrencesOfString:@" " withString:@""];
NSString *newString = @"";
NSString *subString = [text substringToIndex:MIN(text.length, 3)];
newString = [newString stringByAppendingString:subString];
if (subString.length == 3) {
newString = [newString stringByAppendingString:@" "];
}
text = [text substringFromIndex:MIN(text.length, 3)];
if (text.length > 0) {
NSString *subString2 = [text substringToIndex:MIN(text.length, 4)];
newString = [newString stringByAppendingString:subString2];
if (subString2.length == 4) {
newString = [newString stringByAppendingString:@" "];
}
NSString *subString3 = [text substringFromIndex:MIN(text.length, 4)];
newString = [newString stringByAppendingString:subString3];
}
newString = [newString stringByTrimmingCharactersInSet:[characterSet invertedSet]];
if (newString.length >= 14) {
return NO;
}
[self setText:newString];
return NO;
}
@end
- 格式化银行卡信息
#import "JXHBankCardTF.h"
@interface JXHBankCardTF ()
@end
@implementation JXHBankCardTF
- (void)awakeFromNib
{
[super awakeFromNib];
[self setUp];
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 初始化
[self setUp];
}
return self;
}
- (void)setUp
{
}
- (BOOL)valueChangeValueString:(NSString *)string shouldChangeCharactersInRange:(NSRange)range
{
NSString *text = self.text;
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789\\b"];
string = [string stringByReplacingOccurrencesOfString:@" " withString:@""];
if ([string rangeOfCharacterFromSet:[characterSet invertedSet]].location != NSNotFound) {
return NO;
}
text = [text stringByReplacingCharactersInRange:range withString:string];
text = [text stringByReplacingOccurrencesOfString:@" " withString:@""];
NSString *newString = @"";
while (text.length > 0) {
NSString *subString = [text substringToIndex:MIN(text.length, 4)];
newString = [newString stringByAppendingString:subString];
if (subString.length == 4) {
newString = [newString stringByAppendingString:@" "];
}
text = [text substringFromIndex:MIN(text.length, 4)];
}
newString = [newString stringByTrimmingCharactersInSet:[characterSet invertedSet]];
if (newString.length >= 24) {
return NO;
}
[self setText:newString];
return NO;
}
@end
- 限制输入钱款样式(两位小数)
#import "JXHMoneyTF.h"
@implementation JXHMoneyTF
- (BOOL)valueChangeValueString:(NSString *)string shouldChangeCharactersInRange:(NSRange)range
{
NSString *text = self.text;
NSString *decimalSeperator = @".";
NSCharacterSet *charSet = nil;
NSString *numberChars = @"0123456789";
if ([string isEqualToString:decimalSeperator] && [text length] == 0) {
return NO;
}
NSRange decimalRange = [text rangeOfString:decimalSeperator];
BOOL isDecimalNumber = (decimalRange.location != NSNotFound);
if (isDecimalNumber) {
charSet = [NSCharacterSet characterSetWithCharactersInString:numberChars];
if ([string rangeOfString:decimalSeperator].location != NSNotFound) {
return NO;
}
}
else {
numberChars = [numberChars stringByAppendingString:decimalSeperator];
charSet = [NSCharacterSet characterSetWithCharactersInString:numberChars];
}
NSCharacterSet *invertedCharSet = [charSet invertedSet];
NSString *trimmedString = [string stringByTrimmingCharactersInSet:invertedCharSet];
text = [text stringByReplacingCharactersInRange:range withString:trimmedString];
if (isDecimalNumber) {
NSArray *arr = [text componentsSeparatedByString:decimalSeperator];
if ([arr count] == 2) {
if ([arr[1] length] > 2) {
return NO;
}
}
}
self.text = text;
return NO;
}
@end
- 限制任意输入内容
#import "JXHNumberTF.h"
@implementation JXHNumberTF
- (BOOL)valueChangeValueString:(NSString *)string shouldChangeCharactersInRange:(NSRange)range
{
NSString *text = self.text;
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789\\b"];
if ([string rangeOfCharacterFromSet:[characterSet invertedSet]].location != NSNotFound) {
return NO;
}
text = [text stringByReplacingCharactersInRange:range withString:string];
text = [text stringByReplacingOccurrencesOfString:@" " withString:@""];
[self setText:text];
return NO;
}
@end
// 这个方法你可以自己定义,不如说只能输入abc,那么你把
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789\\b"];
// 这个方法改成
NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"abc\\b"];
// 就可以了
github地址: 代码展示
使用方便, 只需要将你需要的输入框样式拖入你的程序中,创建相应的TF 然后把桥接的扩展文件拖入工程后在代理方法里调用封装的方法就可以了