iOS UITextField最大字符數(shù)和字節(jié)數(shù)的限制詳解
前言
這里我給大家?guī)捉M測試用例可以一試,為啥不好用。
1、限制10個(gè)字節(jié),輸入2個(gè)Emoj之后是8個(gè)字節(jié)(一個(gè)Emoj是4個(gè)字節(jié)),此時(shí)再輸入一個(gè)中文,看看結(jié)果如何(中文的UTF8占3個(gè)字節(jié))
2、限制5個(gè)字符,一個(gè)Emoj是2個(gè)字符,其他都是一個(gè)。此時(shí)輸入兩個(gè)Emoj,再輸入中文,然后中文聯(lián)想試試。
就目前的情況來說,看了很多資料,并沒有一個(gè)通用的能限制字符數(shù)和字節(jié)數(shù)的封裝。這里全面進(jìn)行了總結(jié),并進(jìn)行了封裝。歡迎大家下載。
一. 字符限制
1. 錯(cuò)誤方法
常見的這種方法是錯(cuò)誤的,會(huì)導(dǎo)致Emoj表情的截取問題
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(range.length + range.location > textField.text.length)
{
return NO;
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return newLength <= 5;
}
這種限制方法會(huì)導(dǎo)致拼音下出現(xiàn)這種情況,且無法輸入.無法輸入滿5個(gè)字符。在emoj表情也有問題

2. 推薦方法
使用rangeOfComposedCharacterSequencesForRange, 防止在range范圍內(nèi)整詞被截?cái)?/p>
- (void)textFieldDidChange:(UITextField *)textField
{
NSString *toBeString = textField.text;
UITextRange *selectedRange = [textField markedTextRange];
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
// 沒有高亮選擇的字,則對(duì)已輸入的文字進(jìn)行字?jǐn)?shù)統(tǒng)計(jì)和限制,防止中文被截?cái)?
if (!position){
if (toBeString.length > _maxLength){
//中文和emoj表情存在問題,需要對(duì)此進(jìn)行處理
NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, _maxLength)];
textField.text = [toBeString substringWithRange:rangeRange];
}
}
}

二. 字節(jié)限制
1. 限制字節(jié)數(shù)
在UTF8中,英文和數(shù)字是1個(gè)字節(jié),漢子是3個(gè)字節(jié),emoji是3或者4個(gè)字節(jié)。這里的難度比上面更大,如果截取失敗,極有可能出現(xiàn)亂碼。這里我們的做法如下
- (void)textFieldDidChange:(UITextField *)textField
{
NSString *toBeString = textField.text;
//---字節(jié)處理
NSInteger bytesCount = strlen([textField.text UTF8String]);
if (bytesCount > _maxBytesLength) {
NSString *content = [textField.text subStrWithUtf8Len:(int)_maxBytesLength];
textField.text = content;
}
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSString * inputString = [textField.text stringByReplacingCharactersInRange:range withString:string];
//限制字節(jié)數(shù)
if ([inputString length] > 0){
NSInteger len = strlen([inputString UTF8String]);
if (len > _maxBytesLength){
return NO;
}
else {
return YES;
}
}
return YES;
}
這里不能只在進(jìn)行限制,在textFieldDidChange中需要對(duì)中文聯(lián)想做處理才行
三. 放棄鍵盤
1. 能拿到uitextfield的時(shí)候用
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
return [textField resignFirstResponder];
}
2. 點(diǎn)擊view消失的時(shí)候用
[self.view endEditing:YES];
3. 難以獲取的時(shí)候用
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
或者
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
4.Tableview點(diǎn)擊空白處或者滾動(dòng)時(shí)消失
{
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fingerTapped:)];
[self.view addGestureRecognizer:singleTap];
}
#pragma mark- 鍵盤消失
-(void)fingerTapped:(UITapGestureRecognizer *)gestureRecognizer{
[self.view endEditing:YES];
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
[self.view endEditing:YES];
}
四. 正則表達(dá)式限制
請(qǐng)參考 正則表達(dá)式語法表 ,這里我提供了兩種表達(dá)式給大家參考,一個(gè)Int,一個(gè)無unsignedInt
-(BOOL) isTextFieldMatchWithRegularExpression:(NSString *)exporession{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",exporession];
return [predicate evaluateWithObject:self];
}
-(BOOL) isTextFieldIntValue{
return [self isTextFieldMatchWithRegularExpression:@"[-]{0,1}[0-9]*"];
}
-(BOOL) isTextFieldUnsignedIntValue{
return [self isTextFieldMatchWithRegularExpression:@"[0-9]+"];
}
五. UITextfield的鍵盤事件多次回調(diào)問題
1.鍵盤高度遮擋問題
一般出現(xiàn)遮擋的時(shí)候我們用以下代碼,看看當(dāng)前textfield是否在鍵盤下面,在的話算出鍵盤的頂端和textfield的底部的距離,然后做偏移動(dòng)畫
- (void)keyboardWillShow:(NSNotification *)notification {
NSDictionary *userInfo = [notification userInfo];
NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
CGFloat keyboardTop = keyboardRect.origin.y;
CGFloat offset = self.normalTextField.frame.size.height + self.normalTextField.frame.origin.y - keyboardTop;
NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration;
[animationDurationValue getValue:&animationDuration];
if(offset > 0){
// Animate the resize of the text view's frame in sync with the keyboard's appearance.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
CGRect rect = CGRectMake(0.0f, -offset,self.view.frame.size.width,self.view.frame.size.height);
self.view.frame = rect;
[UIView commitAnimations];
}
}
1、真機(jī)
如果使用了中文輸入法,注冊(cè)的keyboardWillShow會(huì)回調(diào)兩次。第一次是鍵盤默認(rèn)高度216,第二次則是加了keyboard的導(dǎo)航欄的高度。
2、模擬器
第一次彈出鍵盤沒有問題

打印userinfo:
(lldb) po userInfo
{
UIKeyboardAnimationCurveUserInfoKey = 7;
UIKeyboardAnimationDurationUserInfoKey = "0.25";
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {414, 226}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {207, 849}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {207, 623}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 736}, {414, 226}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 510}, {414, 226}}";
UIKeyboardIsLocalUserInfoKey = 1;
}
此時(shí)我們?nèi)グ?23旁邊的小圓球會(huì)出現(xiàn)如下的圖:

打印userinfo:
(lldb) po userInfo
{
UIKeyboardAnimationCurveUserInfoKey = 7;
UIKeyboardAnimationDurationUserInfoKey = "0.25";
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {414, 271}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {207, 623}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {207, 600.5}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 510}, {414, 226}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 465}, {414, 271}}";
UIKeyboardIsLocalUserInfoKey = 1;
}
鍵盤被遮擋了。
總結(jié):觀察結(jié)果,發(fā)現(xiàn)了這個(gè)規(guī)律,打印一下時(shí)間,還有一個(gè)問題就是,中文鍵盤第一次啟動(dòng)的時(shí)候會(huì)回調(diào)兩次。
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
所以去掉這句話即可
六. 使用封裝的XXTextField
UITextView , UITextfield 中如果有keyboard的時(shí)候,需要一個(gè)自動(dòng)彈起事件,以及彈起之后的content的偏移對(duì)父view的處理。如果每個(gè)頁面都實(shí)現(xiàn)一次會(huì)非常復(fù)雜。這里我們介紹一種自動(dòng)化的處理機(jī)制。在此之前,先介紹一下文字處理框架.最后給大家推薦一下我寫的 XXTextField ,大家也可以在此基礎(chǔ)上自己添加一些正則表達(dá)式。
1.解決uiview中的textfield 遮擋問題
_textfieldName.keyboardType = UIKeyboardTypeDefault;
_textfieldName.inputType = XXTextFieldTypeOnlyInt;
_textfieldName.maxLength = 5;
_textfieldPwd.inputType = XXTextFieldTypeForbidEmoj;
#import "XXKeyboardManager.h"
@interface XXCorrectVC ()<XXKeyboardManagerShowHiddenNotificationDelegate>
@end
@implementation XXCorrectVC
- (void)viewDidLoad {
[super viewDidLoad];
[[XXKeyboardManager sharedInstance] setDelegate:self];
// Do any additional setup after loading the view from its nib.
}
#pragma mark- KeyBoardShow/Hidden
- (void)showKeyboardWithRect:(CGRect)keyboardRect
withDuration:(CGFloat)animationDuration
{
CGFloat offset = self.textFieldCorrect.frame.size.height + self.textFieldCorrect.frame.origin.y - keyboardRect.origin.y;
if(offset < 0){
return;
}
[UIView animateWithDuration:animationDuration
delay:0.f
options:UIViewAnimationOptionCurveEaseInOut animations:^{
CGRect rect = CGRectMake(0.0f, -offset,self.view.frame.size.width,self.view.frame.size.height);
self.view.frame = rect;
} completion:^(BOOL finished) {
}];
}
- (void)hiddenKeyboardWithRect:(CGRect)keyboardRect
withDuration:(CGFloat)animationDuration
{
[UIView animateWithDuration:animationDuration
delay:0.f
options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.textFieldCorrect.frame = self.view.bounds;
} completion:^(BOOL finished) {
}];
}
@end
2.解決uitableview中鍵盤遮擋問題
/*
* 鍵盤要顯示的時(shí)候
*/
- (void)showKeyboardWithRect:(CGRect)keyboardRect
withDuration:(CGFloat)animationDuration{
CGSize kbSize = keyboardRect.size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
_baseTableView.contentInset = contentInsets;
_baseTableView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, _activeCell.frame.origin) ) {
[_baseTableView scrollRectToVisible:_activeCell.frame animated:YES];
}
}
/*
* 鍵盤要消失的時(shí)候
*/
- (void)hiddenKeyboardWithRect:(CGRect)keyboardRect
withDuration:(CGFloat)animationDuration{
_baseTableView.contentInset = UIEdgeInsetsZero;
_baseTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)各位Android開發(fā)者們能有所幫助,如果有疑問大家可以留言交流。
- iOS中修改UITextField占位符字體顏色的方法總結(jié)
- IOS UI學(xué)習(xí)教程之設(shè)置UITextField各種屬性
- iOS應(yīng)用開發(fā)中使UITextField實(shí)現(xiàn)placeholder屬性的方法
- 解決iOS UITextField 編輯時(shí)文本偏移問題
- iOS開發(fā)之自定義UITextField的方法
- iOS UITextField、UITextView只限輸入中文、英文、數(shù)字及實(shí)時(shí)限制字符個(gè)數(shù)的封裝實(shí)現(xiàn)代碼
- 解決iOS7上UITextField限制字?jǐn)?shù)輸入導(dǎo)致崩潰問題的方法
- IOS 中UITextField,UITextView,UILabel 根據(jù)內(nèi)容來計(jì)算高度
- iOS輸入框(UITextField)密碼明暗文切換方法
- iOS中監(jiān)聽UITextField值改變事件的方法實(shí)例
相關(guān)文章
iOS開發(fā)驗(yàn)證判斷語句之正則表達(dá)式小結(jié)
最近在公司接手重構(gòu)一個(gè)項(xiàng)目,發(fā)現(xiàn)之前的開發(fā)在驗(yàn)證格式這塊寫的太亂了,到處都有相關(guān)的驗(yàn)證代碼,所以就有了這篇文章,供自己收藏也分享給有需要的朋友們參考借鑒,下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2016-12-12
iOS毛玻璃效果的實(shí)現(xiàn)及圖片模糊效果的三種方法
App設(shè)計(jì)時(shí)往往會(huì)用到一些模糊效果或者毛玻璃效果,iOS目前已提供一些模糊API可以讓我們方便是使用,本文給大家介紹iOS毛玻璃效果的實(shí)現(xiàn)及圖片模糊效果的三種方法,感興趣的朋友一起學(xué)習(xí)吧2016-01-01
實(shí)例講解iOS應(yīng)用UI開發(fā)之基礎(chǔ)動(dòng)畫的創(chuàng)建
這篇文章主要介紹了iOS應(yīng)用UI開發(fā)之基礎(chǔ)動(dòng)畫的創(chuàng)建,以關(guān)鍵幀動(dòng)畫作為重要知識(shí)點(diǎn)進(jìn)行講解,需要的朋友可以參考下2015-11-11
iOS 請(qǐng)求權(quán)限封裝類的實(shí)例代碼
下面小編就為大家分享一篇iOS 請(qǐng)求權(quán)限封裝類的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01
iOS Remote Notification遠(yuǎn)程消息推送處理
這篇文章主要為大家詳細(xì)介紹了iOS Remote Notification遠(yuǎn)程消息推送處理,感興趣的小伙伴們可以參考一下2016-09-09

