先說說記錄這個的原因吧威始,關于限制UITextField
的輸入字數(shù)的各種需求,已經(jīng)疲軟了像街,工作幾年中用的還真不少黎棠,有只要字數(shù)長度的,也有字符長度的镰绎,當然這個就包括中文和英文葫掉,還有.....標點符號也分中文和英文的,每次都多不情愿的寫這個地方跟狱,閑來無事俭厚,就來記錄一下,方便大家驶臊,若有不對的地方挪挤,多多指教哈。
關于UITextField
大家肯定對下面這個方法非常熟悉
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
那么這個函數(shù)的大概意思是什么呢关翎?我是這么理解的(個人認為)
由于返回的是個 BOOL 所以我猜想大概就是我們在輸入的時候扛门,是否對UITextField 的內(nèi)容進行修改
下面來簡單分析下參數(shù)
textField
這個參數(shù)大家都懂,就是響應該協(xié)議的UITextField對象
range
在這個函數(shù)中纵寝,添加了打印信息论寨,測試了下
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(@" 打印信息:%lu -----%lu ",(unsigned long)range.location,(unsigned long)range.length);
}
//打印log
2017-01-25 17:48:49.826 TestObject[5502:683375] 打印信息toBeString:Zxtgfd
2017-01-25 17:48:50.506 TestObject[5502:683375] 打印信息:6 -----0
2017-01-25 17:48:50.508 TestObject[5502:683375] 打印信息toBeString:Zxtgfda
2017-01-25 17:48:51.894 TestObject[5502:683375] 打印信息:6 -----1
由此可以看到,在輸入的時候爽茴,range.length為0葬凳,range.location為插入時的位置 ,range.length為1時室奏,是我在點擊刪除的時候打印的火焰,應該可以表示刪除(不確定)
string
string.length為0時,表示刪除胧沫。
限制輸入長度
- 1 如果只是輸入英文狀態(tài)昌简,或者數(shù)字狀態(tài)占业,那么我們我們可以利用這個函數(shù),實現(xiàn)方法為:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(@" 打印信息:%lu -----%lu ",(unsigned long)range.location,(unsigned long)range.length);
if (textField.text.length + string.length > kMaxNumber) {
return NO;
}
//刪除按鈕
if (string.length == 0)
{
return YES;
}
return YES;
}
- 2 但是纯赎,如果要涉及到中文的話谦疾,這樣就不行了。因為犬金,在輸入中文的時候念恍,如果你還沒有確定所輸入的中文,那么
UITextField
此時接收的并不是中文佑附,而是對應的拼音樊诺,比如你想輸入漢字君不見黃河之水天上來
那么對應的拼音則是junbujianhuanghezhishuitianshanglai
這么一來,比如你想限制的輸入個數(shù)為10 那么只能輸入到junbujianh
這個位置音同。
那么我們該怎么解決問題呢词爬,進入API我們可以發(fā)現(xiàn)。
UITextField : UIControl ---- UITextField繼承自UIControl
有如下函數(shù)
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
UIControlEventTouchDown = 1 << 0, // on all touch downs
UIControlEventTouchDownRepeat = 1 << 1, // on multiple touchdowns (tap count > 1)
UIControlEventTouchDragInside = 1 << 2,
UIControlEventTouchDragOutside = 1 << 3,
UIControlEventTouchDragEnter = 1 << 4,
UIControlEventTouchDragExit = 1 << 5,
UIControlEventTouchUpInside = 1 << 6,
UIControlEventTouchUpOutside = 1 << 7,
UIControlEventTouchCancel = 1 << 8,
UIControlEventValueChanged = 1 << 12, // sliders, etc.
UIControlEventPrimaryActionTriggered NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 13, // semantic action: for buttons, etc.
UIControlEventEditingDidBegin = 1 << 16, // UITextField
UIControlEventEditingChanged = 1 << 17,
UIControlEventEditingDidEnd = 1 << 18,
UIControlEventEditingDidEndOnExit = 1 << 19, // 'return key' ending editing
UIControlEventAllTouchEvents = 0x00000FFF, // for touch events
UIControlEventAllEditingEvents = 0x000F0000, // for UITextField
UIControlEventApplicationReserved = 0x0F000000, // range available for application use
UIControlEventSystemReserved = 0xF0000000, // range reserved for internal framework use
UIControlEventAllEvents = 0xFFFFFFFF
};
我們可以利用此函數(shù)和對應的枚舉UIControlEventEditingChanged
來監(jiān)測輸入的內(nèi)容變化权均,從而控制輸入的字數(shù)
代碼如下
- (void)textFiledDidChange:(UITextField *)textField
{
if (kMaxNumber == 0) return;
NSString *toBeString = textField.text;
NSLog(@" 打印信息toBeString:%@",toBeString);
NSString *lang = [[textField textInputMode] primaryLanguage]; // 鍵盤輸入模式
if ([lang isEqualToString:@"zh-Hans"]) { // 簡體中文輸入顿膨,包括簡體拼音,健體五筆叽赊,簡體手寫
//判斷markedTextRange是不是為Nil恋沃,如果為Nil的話就說明你現(xiàn)在沒有未選中的字符,
//可以計算文字長度必指。否則此時計算出來的字符長度可能不正確
UITextRange *selectedRange = [textField markedTextRange];
//獲取高亮部分(感覺輸入中文的時候才有)
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
// 沒有高亮選擇的字囊咏,則對已輸入的文字進行字數(shù)統(tǒng)計和限制
if (!position)
{
//中文和字符一起檢測 中文是兩個字符
if ([toBeString getStringLenthOfBytes] > kMaxNumber)
{
textField.text = [toBeString subBytesOfstringToIndex:kMaxNumber];
}
}
}
else
{
if ([toBeString getStringLenthOfBytes] > kMaxNumber)
{
textField.text = [toBeString subBytesOfstringToIndex:kMaxNumber];
}
}
}
其中有正則表達式的驗證,方法我是寫在NSString
的擴展中的塔橡,具體如下
//.h文件
#import <Foundation/Foundation.h>
@interface NSString (category)
- (NSInteger)getStringLenthOfBytes;
- (NSString *)subBytesOfstringToIndex:(NSInteger)index;
@end
//.m文件
#import "NSString+category.h"
@implementation NSString (category)
- (NSInteger)getStringLenthOfBytes
{
NSInteger length = 0;
for (int i = 0; i<[self length]; i++) {
//截取字符串中的每一個字符
NSString *s = [self substringWithRange:NSMakeRange(i, 1)];
if ([self validateChineseChar:s]) {
NSLog(@" s 打印信息:%@",s);
length +=2;
}else{
length +=1;
}
NSLog(@" 打印信息:%@ %ld",s,(long)length);
}
return length;
}
- (NSString *)subBytesOfstringToIndex:(NSInteger)index
{
NSInteger length = 0;
NSInteger chineseNum = 0;
NSInteger zifuNum = 0;
for (int i = 0; i<[self length]; i++) {
//截取字符串中的每一個字符
NSString *s = [self substringWithRange:NSMakeRange(i, 1)];
if ([self validateChineseChar:s])
{
if (length + 2 > index)
{
return [self substringToIndex:chineseNum + zifuNum];
}
length +=2;
chineseNum +=1;
}
else
{
if (length +1 >index)
{
return [self substringToIndex:chineseNum + zifuNum];
}
length+=1;
zifuNum +=1;
}
}
return [self substringToIndex:index];
}
//檢測中文或者中文符號
- (BOOL)validateChineseChar:(NSString *)string
{
NSString *nameRegEx = @"[\\u0391-\\uFFE5]";
if (![string isMatchesRegularExp:nameRegEx]) {
return NO;
}
return YES;
}
//檢測中文
- (BOOL)validateChinese:(NSString*)string
{
NSString *nameRegEx = @"[\u4e00-\u9fa5]";
if (![string isMatchesRegularExp:nameRegEx]) {
return NO;
}
return YES;
}
- (BOOL)isMatchesRegularExp:(NSString *)regex {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
return [predicate evaluateWithObject:self];
}
@end
當然梅割,如果遇到UITextView
限制字數(shù)的時候,由于不是繼承1
所以沒有addtarget
方法葛家,但是可以通過添加通知UITextViewTextDidChangeNotification
的方法來監(jiān)測 户辞,方法還是和上面一樣。
- 總結 針對上面兩種不同的方案癞谒,在不同的時候可以選擇不同的方案底燎。希望對大家有幫助,有什么不對的地方弹砚,還望不吝賜教双仍。