UITextView,UITextfield中有很多坑,网上的方法也很多,但是用过之后暂时没有发现一个好用。这里我给大家几组测试用例可以一试,为啥不好用。

  1. 限制10个字节,输入2个Emoj之后是8个字节(一个Emoj是4个字节),此时再输入一个中文,看看结果如何(中文的UTF8占3个字节)
  2. 限制5个字符,一个Emoj是2个字符,其他都是一个。此时输入两个Emoj,再输入中文,然后中文联想试试。

就目前的情况来说,看了很多资料,并没有一个通用的能限制字符数和字节数的封装。这里全面进行了总结,并进行了封装。欢迎大家下载。

一. 字符限制

1. 错误方法

常见的这种方法是错误的,会导致Emoj表情的截取问题

1
2
3
4
5
6
7
8
9
10
- (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;
}

这种限制方法会导致拼音下出现这种情况,且无法输入.无法输入满5个字符。在emoj表情也有问题

2. 推荐方法

使用rangeOfComposedCharacterSequencesForRange, 防止在range范围内整词被截断.因为中文的UTF8是3字节,Emoj是4个字节,且不能边输入边限制,否则中文联想的时候就无法继续输入。只能输入后在textfieldchange的时候进行截断。
综上所述,思路如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- (void)textFieldDidChange:(UITextField *)textField
{
NSString *text = textField.text;
// NSLog(@"text:%@",text); UITextRange *selectedRange = [textField markedTextRange];
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0]; // 没有高亮选择的字,则对已输入的文字进行字数统计和限制,防止中文被截断 if (!position){
//---字符处理
if (text.length > _maxLength){
//中文和emoj表情存在问题,需要对此进行处理
NSRange range;
NSUInteger inputLength = 0;
for(int i=0; i < text.length && inputLength <= _maxLength; i += range.length) {
range = [textField.text rangeOfComposedCharacterSequenceAtIndex:i];
inputLength += [text substringWithRange:range].length;
if (inputLength > _maxLength) {
NSString* newText = [text substringWithRange:NSMakeRange(0, range.location)];
textField.text = newText;
}
}
}
}
}

二. 字节限制

1. 限制字节数

在UTF8中,英文和数字是1个字节,汉子是3个字节,emoji是3或者4个字节。这里的难度比上面更大,如果截取失败,极有可能出现乱码。这里我们的做法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
- (void)textFieldDidChange:(UITextField *)textField
{
NSString *text = textField.text;
// NSLog(@"text:%@",text); UITextRange *selectedRange = [textField markedTextRange];
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0]; // 没有高亮选择的字,则对已输入的文字进行字数统计和限制,防止中文被截断 if (!position){
//---字节处理
//Limit
NSUInteger textBytesLength = [textField.text lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
if (textBytesLength > _maxBytesLength) {
NSRange range;
NSUInteger byteLength = 0;
for(int i=0; i < text.length && byteLength <= _maxBytesLength; i += range.length) {
range = [textField.text rangeOfComposedCharacterSequenceAtIndex:i];
byteLength += strlen([[text substringWithRange:range] UTF8String]);
if (byteLength > _maxBytesLength) {
NSString* newText = [text substringWithRange:NSMakeRange(0, range.location)];
textField.text = newText;
}
}
}
}
if (self.textFieldChange) {
self.textFieldChange(self,textField.text);
}
}

三. 放弃键盘

1. 能拿到uitextfield的时候用

1
2
3
4
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
return [textField resignFirstResponder];
}

2. 点击view消失的时候用

1
[self.view endEditing:YES];

3. 难以获取的时候用

1
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

或者

1
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];

2.Tableview点击空白处或者滚动时消失

1
2
3
4
5
6
7
8
9
10
11
12
{
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];
}

四. 正则表达式限制

请参考正则表达式语法表,这里我提供了两种表达式给大家参考,一个Int,一个无unsignedInt

1
2
3
4
5
6
7
8
9
10
11
-(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的键盘事件多次回调问题

1.键盘高度遮挡问题

一般出现遮挡的时候我们用以下代码,看看当前textfield是否在键盘下面,在的话算出键盘的顶端和textfield的底部的距离,然后做偏移动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- (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. 真机
    如果使用了中文输入法,注册的keyboardWillShow会回调两次。第一次是键盘默认高度216,第二次则是加了keyboard的导航栏的高度。

  2. 模拟器
    第一次弹出键盘没有问题

打印userinfo:

1
2
3
4
5
6
7
8
9
10
11
(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;
}

此时我们去按123旁边的小圆球会出现如下的图:

打印userinfo:

1
2
3
4
5
6
7
8
9
10
11
(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;
}

键盘被遮挡了。

总结:观察结果,发现了这个规律,打印一下时间,还有一个问题就是,中文键盘第一次启动的时候会回调两次。

1
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

所以去掉这句话即可

六. 使用封装的XXTextField

UITextView,UITextfield中如果有keyboard的时候,需要一个自动弹起事件,以及弹起之后的content的偏移对父view的处理。如果每个页面都实现一次会非常复杂。这里我们介绍一种自动化的处理机制。在此之前,先介绍一下文字处理框架.最后给大家推荐一下我写的XXTextField,大家也可以在此基础上自己添加一些正则表达式。使用方法很简单.欢迎加入QQ群:237305299 ,一起探讨iOS技术问题

1.解决uiview中的textfield 遮挡问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
_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中键盘遮挡问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
* 键盘要显示的时候
*/
- (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];
}http://www.90168.org/
} /*
* 键盘要消失的时候
*/
- (void)hiddenKeyboardWithRect:(CGRect)keyboardRect
withDuration:(CGFloat)animationDuration{
_baseTableView.contentInset = UIEdgeInsetsZero;
_baseTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}

UITextField最大字符数和最大字节数的限制的更多相关文章

  1. Java中文字符所占的字节数

    Java语言中,中文字符所占的字节数取决于字符的编码方式,一般情况下,采用ISO8859-1编码方式时,一个中文字符与一个英文字符一样只占1个字节:采用GB2312或GBK编码方式时,一个中文字符占2 ...

  2. Notepad++查看文本文件的总的字符数、GBK字节数、UTF8字节数

    如果其编码是 小结:UTF-8编码下,一个汉字占3字节,GBK编码下,一个汉字占2字节:

  3. 关于char/varchar(n)中n的探究:字符数or字节数

    [问题来源]将设计的数据库表展示的时候,yu哥问我,你的那个top_info字段定义的类型是varchar(100),为什么是100呢,这100的长度能存多少个中文? 当时的想法就是,这个100能存多 ...

  4. Java字符串中常用字符占用字节数

    java中一个char型的数据(也就是一个字符)占两个字节.而Java中常用的字符包括数字.英文字母.英文符号.中文汉字.中文符号等,若在字符串中包含里面的多种字符,它们是否都占两个字符呢?答案是否定 ...

  5. Java不同编码方式,中英文字符所占字节数

    测试代码 public class Test { public static void main(String[] args){ String[] charsetNames={ "UTF-8 ...

  6. UITextView 和 UITextField限制字符数和表情符号

    UITextField限制字符数 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)r ...

  7. JS计算字符长度、字节数 -- 转

    一个汉字在UTF-8编码中占用几个字节? 占用3个字节的范围 U+2E80 - U+2EF3 : 0xE2 0xBA 0x80 - 0xE2 0xBB 0xB3 共 115 个 U+2F00 - U+ ...

  8. Java中字符编码和字符串所占字节数 .

    首 先,java中的一个char是2个字节.java采用unicode,2个字节来表示一个字符,这点与C语言中不同,C语言中采用ASCII,在大多数 系统中,一个char通常占1个字节,但是在0~12 ...

  9. 编码占用的字节数 1 byte 8 bit 1 sh 1 bit 中文字符编码 2. 字符与编码在程序中的实现 变长编码 Unicode UTF-8 转换 在网络上传输 保存到磁盘上 bytes

    小结: 1.UNICODE 字符集编码的标准有很多种,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等: 2 服务器->网页 utf-8 ...

随机推荐

  1. 由浅入深剖析.htaccess

    转自:http://blog.csdn.net/21aspnet/article/details/6908025 [-] htaccess文件使用前提 htaccess基本语法介绍 现学现用学习正则表 ...

  2. Hibernate基本CRUD

    1 hibernate 框架介绍 冬眠:开发的代码基本不变. 1.1回顾jdbc Java提供的标准的数据访问的API 作用:完成应用程序java程序中的数据和db中的数据进行交换. 工作过程: A ...

  3. iOS 全局禁止横屏,但UIWebView 全屏播放视频,横屏,解决办法(任意页面横竖屏或禁止)

    iOS 全局禁止横屏,但UIWebView 全屏播放视频,横屏,解决办法 时间 2015-07-14 20:59:00  博客园-原创精华区 原文  http://www.cnblogs.com/fe ...

  4. php 投票系统练习

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. PHP面试题集

    汗~~做了一下网络上的php题目,不知不觉做到现在.....把答案贴出来如果有问题请欢迎补充和指正 1.用PHP打印出前一天的时间格式是2006-5-10 22:21:21(2分)   $a = da ...

  6. sdut 2603:Rescue The Princess(第四届山东省省赛原题,计算几何,向量旋转 + 向量交点)

    Rescue The Princess Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Several days ago, a b ...

  7. 获取Windows下某进程监听的TCP/UDP端口

    1.在Windows下用CMD netstat命令可以获得当前进程监听端口号的信息,如netstat -ano可以看到IP.port.状态和监听的PID. 那么可以执行CMD这个进程得到监听的端口号信 ...

  8. oracle相关环境变量配置

    ORACLE_HOME:D:\Program File\oracle\product\10.2.0\db_1 ORACLE_SID:orcl Path中增加:D:\ProgramFile\oracle ...

  9. HP SAN Switch光纖交換機命令行畫zone

    有時候我們無法登陸網頁交互界面去操縱交換機,如下提供了命令行方式從交換機劃zone 1.創建別名 alicreate "SummaryDB_N", "211,14; 21 ...

  10. hdu 5033 单调栈 ****

    看出来是单调栈维护斜率,但是不会写,2333,原来是和询问放在一起的 #include <iostream> #include <cstdio> #include <cs ...