iOS UITextField最大字符数和字节数的限制详解

前言

这里我给大家几组测试用例可以一试,为啥不好用。

1、限制10个字节,输入2个Emoj之后是8个字节(一个Emoj是4个字节),此时再输入一个中文,看看结果如何(中文的UTF8占3个字节)

2、限制5个字符,一个Emoj是2个字符,其他都是一个。此时输入两个Emoj,再输入中文,然后中文联想试试。

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

一. 字符限制

1. 错误方法

常见的这种方法是错误的,会导致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;
}

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

2. 推荐方法

使用rangeOfComposedCharacterSequencesForRange, 防止在range范围内整词被截断

- (void)textFieldDidChange:(UITextField *)textField
{
 NSString *toBeString = textField.text;

 UITextRange *selectedRange = [textField markedTextRange];
 UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];

 // 没有高亮选择的字,则对已输入的文字进行字数统计和限制,防止中文被截断
 if (!position){
 if (toBeString.length > _maxLength){
  //中文和emoj表情存在问题,需要对此进行处理
  NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, _maxLength)];
  textField.text = [toBeString substringWithRange:rangeRange];
 }
 }
}

二. 字节限制

1. 限制字节数

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

- (void)textFieldDidChange:(UITextField *)textField
{
 NSString *toBeString = textField.text;
 //---字节处理
 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];

 //限制字节数
 if ([inputString length] > 0){
 NSInteger len = strlen([inputString UTF8String]);
 if (len > _maxBytesLength){
  return NO;
 }
 else {
  return YES;
 }
 }
 return YES;
}

这里不能只在进行限制,在textFieldDidChange中需要对中文联想做处理才行

三. 放弃键盘

1. 能拿到uitextfield的时候用

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

2. 点击view消失的时候用

[self.view endEditing:YES];

3. 难以获取的时候用

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

或者

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

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

{
 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

-(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的底部的距离,然后做偏移动画

- (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:

(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:

(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;
}

键盘被遮挡了。

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

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

所以去掉这句话即可

六. 使用封装的XXTextField

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

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中键盘遮挡问题

/*
 * 键盘要显示的时候
 */
- (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];
 }
}

/*
 * 键盘要消失的时候
 */
- (void)hiddenKeyboardWithRect:(CGRect)keyboardRect
     withDuration:(CGFloat)animationDuration{
 _baseTableView.contentInset = UIEdgeInsetsZero;
 _baseTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对各位Android开发者们能有所帮助,如果有疑问大家可以留言交流。

时间: 2016-11-29

iOS输入框(UITextField)密码明暗文切换方法

在做明暗文切换(密码输入框)的时候遇见一个坑,就是切换secureTextEntry的时候,输入框的光标会偏移,下面列出了一个解决办法及一种明暗文切换的方法 - (IBAction)pwdTextSwitch:(UIButton *)sender { // 前提:在xib中设置按钮的默认与选中状态的背景图 // 切换按钮的状态 sender.selected = !sender.selected; if (sender.selected) { // 按下去了就是明文 NSString *temp

iOS中修改UITextField占位符字体颜色的方法总结

前言 最近学了UITextField控件, 感觉在里面设置占位符非常好, 给用户提示信息, 于是就在想占位符的字体和颜色能不能改变呢?下面是小编的一些简单的实现,有需要的朋友们可以参考. 修改UITextField的占位符文字颜色主要有三个方法: 1.使用attributedPlaceholder属性 @property(nullable, nonatomic,copy) NSAttributedString *attributedPlaceholder NS_AVAILABLE_IOS(6_0

解决iOS UITextField 编辑时文本偏移问题

1.在cell中添加UITextField,在编辑的时候总是出现文本偏移问题,编辑结束时回复正常,解决方式如下: (1)代码创建UITextField,并添加上去,设置textField的一些属性: - (UITextField *)textField{ if (_textField == nil) { _textField = [UITextField new]; _textField.borderStyle = UITextBorderStyleNone; _textField.conten

iOS 中 使用UITextField格式化银行卡号码的解决方案

今天做格式化银行卡,避免重复造轮子,找度娘查了下,看到一个不错的实现方式,记录下来,并附带实现思路 #pragma mark - UITextFieldDelegate UITextField键入字符后调用 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { //拿到为改变前的字符串 NSStri

iOS App开发中UITextField组件的常用属性小结

重点属性 在 Xcode 中使用 IB 给视图拖上去一个文本框后,选中文本框,可以在Attribute Inspector中设置其各种属性. Attribute Inspector 分为三部分,分别是 Text Field.Control 和 View 部分.我们重点看看 Text Field 部分. Text Field 部分有以下选项: 1.Text :设置文本框的默认文本. 2.Placeholder : 可以在文本框中显示灰色的字,用于提示用户应该在这个文本框输入什么内容.当这个文本框中

iOS UIAlertController中UITextField添加晃动效果与边框颜色详解

前言 大家都知道在iOS8中引入了UIAlertController,通过UIAlertController可以方便的添加文本框进行编辑,但是,在输入错误的内容时,如何对用户进行提醒就成了问题,因为UIAlertController中的所有UIAlertAction都会导致UIAlertController的消失.这里,我就描述两种提示的方法,分别是晃动文本框和修改边框的颜色.下面话不多说了,来一起看看详细的实现方法吧. 晃动UITextField 晃动UITextField其实就是对它添加一个

iOS改变UITextField占位文字颜色的三种方法

有时,UITextField自带的占位文字的颜色太浅或者不满足需求,所以需要修改,而UITextField没有直接的属性去修改占位文字的颜色,所以只能通过其他间接方式去修改. 例如:系统默认的占位文字颜色太浅 需要加深颜色,或者改变颜色 示例: 核心代码 方法一:通过attributedPlaceholder属性修改占位文字颜色 CGFloat viewWidth = self.view.bounds.size.width; CGFloat textFieldX = 50; CGFloat te

IOS UI学习教程之设置UITextField各种属性

UITextField是IOS中非常常用的一个控件,用来接收用户输入信息,完成应用和用户的交互.它的主要属性设置如下: //初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGRectMake(20, 20, 130, 30)]; //设置边框样式,只有设置了才会显示边框样式 text.borderStyle = UITextBorderStyleRoundedRect; typedef enu

iOS开发之自定义UITextField的方法

UITextField是IOS开发中用户交互中重要的一个控件,常被用来做账号密码框,输入信息框等. 观察效果图 UITextField有以下几种特点: 1.默认占位文字是灰色的 2.当光标点上去时,占位文字变为白色 3.光标是白色的 接下来我们通过不同的方法来解决问题 一.将xib中的UITextField与代码关联 通过NSAttributeString方法来更改占位文字的属性 (void)viewDidLoad { [super viewDidLoad]; // Do any additio

IOS 开发之自定义按钮实现文字图片位置随意定制

IOS 开发之自定义按钮实现文字图片位置随意定制 可能有些看到这篇文章的朋友会觉得很不屑:"按钮谁不会自定义?还需要看你的?" 也确实,按钮是我们项目中最常见的控件之一,天天在使用.对于不同类型的按钮,我们是否有更加简便的方法来实现需求是我们需要做的.这里我提出自己的两种方法,您可以对你自己平时自定义按钮的方法做一下对比,看看哪种方法更加简单. 多说一句,千万不要觉得知识简单,觉得自己会了,没必要学习.'往往简单的东西存在大智慧'(这个比给满分),知识都是慢慢积累出来的. 按钮是应用中

iOS开发之自定义图片拉伸功能

需求 为了减小app体积,同时为了适配不同尺寸屏幕或不同应用场景,很多图片素材都是标准通用的,比如IM消息气泡.按钮阴影效果等,但直接使用这些素材会产生一些问题,假如我们需要实现以下效果,即使用图片为账号密码输入框添加阴影效果: 图片素材: 直接使用图片实现的效果与需求效果对比: 经过自定义拉伸调整过后,最终效果: 实现 将storyboard中的控件关联到代码文件中,accountTextBgImageView 为textFiled 下的背景图片视图,实现代码如下: UIImage *text

iOS开发定时器的三种方法分享

前言 在开发中,很多时候我们需要用到定时器实时刷新某个数值.这个时候我们就需要用到定时器,这里,我为大家推荐三种方法,分别是:NSTimer.CADisplayLink.GCD.接下来我就一一介绍它们的用法.希望能帮到大家. 一.NSTimer(一般用于定时的更新一些非界面上的数据) 1. 创建方法 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(action:

ios开发中时间转换的方法集锦

在开发iOS程序时,有时候需要将时间格式调整成自己希望的格式,这个时候我们可以用NSDateFormatter类来处理. 例如: //实例化一个NSDateFormatter对象 NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; //设定时间格式,这里可以设置成自己需要的格式 [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; //用[NSDate d

iOS使用UIKeyInput自定义密码输入框的方法示例

前言 开发中很多地方都会遇到密码输入,这时候往往需要根据UI设计自定义.这里遵守UIKeyInput,实现协议中的方法,让自定义View可以进行文字输入:再通过func draw(_ rect: CGRect)绘制现自定义UI:使用配置类来统一接口:使用代理来管理各种输入相关的事件.文章末尾有提供OC和Swift双语的CLDemo下载,这里讲解就使用Swift. 1.遵守UIKeyInput协议,实现文字输入 遵守UIKeyInput协议,实现协议中- (BOOL)hasText. - (voi

全面解析iOS应用中自定义UITableViewCell的方法

有时候我们需要自己定义UITableViewCell的风格,其实就是向行中添加子视图.添加子视图的方法主要有两种:使用代码以及从.xib文件加载.当然后一种方法比较直观. 一.基本用法 我们这次要自定义一个Cell,使得它像QQ好友列表的一行一样:左边是一张图片,图片的右边是三行标签: 当然,我们不会搞得这么复杂,只是有点意思就行. 1.运行Xcode 4.2,新建一个Single View Application,名称为Custom Cell: 2.将图片资源导入到工程.为此,我找了14张50

iOS开发 全机型适配解决方法

最近做项目,对于IPhone 手机机型适配很是头疼,所以整理下网上资料,记录下来,也许能帮助到正看文章的你, 今天打算跟大家聊聊最近研究的全机型适配思路. 当前我们需要适配的iPhone机型有4s.5s.6s.6Plus四种机型.它们的尺寸分别是 iphone4s {320, 480}                           960*640  iphone5 5s {320, 568}                       1136*640  iphone6 6s   {375

GMap.Net开发之自定义Marker使用方法

自定义Marker,可以理解为在地图上自定义图标(Custom Marker),先看看GMap的地图和图标的显示方式: Map控件上可以添加Overlay(图层),可以添加多个图层,先添加的图层在下面显示. 图层上可以添加GMapMarker,当然也可以添加GMapPolygon和GMapRoute,后续介绍. 在地图的使用中常要求的功能就是添加自定义图标,可以点击图标.删除图标.拖动图标.高亮图标等. 下面介绍这些功能的实现(主要是基于WinForm的,WPF的可以参考官方Demo实现): 1

iOS应用开发中使UITextField实现placeholder属性的方法

我们都知道iOS开发中的UITextField有个placeholder属性,placeholder可以很方便引导用户输入.但是UITextView却没有placeholder属性. 一.猥琐的方法 如何让UITextView也有placeholder功能呢?今天给各位分享一个比较猥琐的做法.思路大概是这样的: 把UITextView的text当placeholder使用. 在开始编辑的代理方法里清除placeholder. 在结束编辑的代理方法里在设置placeholder. 实现方法: 1.