iOS对textField进行字符长度限制的办法
在项目开发过程中,遇到这么一个需求,编辑标签时,输入的最大长度需要限制为24个字节。
查阅了一些材料,并参考了之前项目的相关处理办法,今天在这里总结一下解决方案。
1.写一个截取字符串的方法,将超长的字符串截取成符合长度的字符串。如果内容超长,就干掉最后一个字,再判断是否超过限制长度,如此循环,直到满足长度限制要求。这里注意一下,直接使用length方法,返回的字符数,而不是字节数,lengthOfBytesUsingEncoding可返回指定字符编码的字节数。
这里遇到了一个特殊的问题:当字符串最后一个字符是emoji表情符号时,如果长度超限,会发现截取后的字符串最后有乱码。究其原因,一般的汉字和英文字符,都只占一个lengh单位,例如“我是Tom”的lengh就是5。但是表情符号可能占多个length单位,比如2个或者3个,甚至更多。所以,只把最后一个length单位截取掉,其实是没有把该表情符号完全删除掉的。幸运的是,我们仍然可以使用lengthOfBytesUsingEncoding来解决此问题,当一个utf8字符的编码不完整时,我们发现lengthOfBytesUsingEncoding返回0,把这种情况也处理一下即可。
- /**
- * 截取字符串,使字符串满足最大长度要求
- *
- * @param sourceString 待截取的字符串
- *
- * @return 截取后的字符串
- */
- -(NSString*)truncatedString:(NSString*)sourceString
- {
- NSString *temp = [NSString stringWithString:sourceString];
- while(YES)
- {
- NSInteger stringLen = [temp lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
- if(stringLen == && temp.length != )
- {
- //当字符串的length不为零,stringLen为0时,代表字符串包含了不完整的UTF8编码的字符,取自身length-1的字符串
- temp = [temp substringToIndex:temp.length-];
- continue;
- }
- if (stringLen <= kMaxByteOfAlarmName) {
- //字符串符合长度要求
- break;
- }
- else
- {
- //字符串过长,取自身length-1的字符串
- temp = [temp substringToIndex:temp.length-];
- }
- }
- return temp;
- }
2.添加对UITextField的编辑变化事件的监听:
- [self.textField addTarget:self action:@selector(textLengthChange:) forControlEvents:UIControlEventEditingChanged];
3.实现对应的action:
-(void)textLengthChange:(id)sender
{
UITextField * textField=(UITextField*)sender;
if (textField.markedTextRange == nil)
{
NSString *truncatedString = [self truncatedString:textField.text];
if(![textField.text isEqualToString:truncatedString])
{
textField.text = truncatedString;
}
}
}
说明:
另外,中文输入时,和平时英文输入会不太一样,中文输入会出现正在输入拼音,还没有选汉字,拼音已经上去了:
这时,拼音本身占的字节可能大于选字后的汉字所占的字节,例如输入zhong,占5个字节,而如果用户选择“中”,只占三个字节。如果不专门考虑这种情况,就会出现明明还可以再输一个中文汉字,但是输入拼音的时候没法完成zhong的拼音输入。所以需要判断当时textField是否有已选中的内容。至于为什么要先判断是否截取前后相等,是因为如果截取了,光标会自动跑到最后去,所以当用户输入没有超长时,我们最好不要改变光标的位置。
4.针对步骤3中的图,如果在出现图中的状态下直接保存,那么textfiled会把未转换为汉字的拼音也一起保存进去。所以还需要在使用textfield的内容前再进行一下处理,把超出的部分删除,再执行一遍截取:
- self.textField.text = [self truncatedString:self.textField.text];
Done。如果有什么问题,欢迎留言指出,一起讨论。
补充点东西:
为什么不用UITextField的代理方法shouldChangeCharactersInRange?
目前看来,此方法无法捕捉粘贴、拼音转汉字和联想(例如使用拼音输“中国”后,直接再键盘的候选词中可以选“万岁”)输入导致的变化。所以不采用。
更新:
2016.7.25:将相同的代码提取成方法,增加对表情等特殊字符的处理。另外,考虑一种场景,即输入时,光标不在末尾的情况,那么随着用户的输入,最后的字符将会删除。体验更好的情况应该是删除新输入的字符串的末尾。但由于我们无法获取到新输入的字符串(shouldChangeCharactersInRange 有局限性),可以考虑直接撤销本次更改,保留上次的内容(这要求每次输入完成后,需要将现有的内容保存起来)。鉴于这种场景很少见,且当前处理也不会出现超限的问题,暂时不处理。
iOS对textField进行字符长度限制的办法的更多相关文章
- url字符长度限制解决办法
前段时间,同事往系统上传相关文档,发现输入失败,找到了我了. 开始以为数据库字段属性问题,修改后未解决随调试系统,发现没有走到后台程序,发现 ajax没有传值,各种测试问题情况,后来同事发现是url字 ...
- iOS 学习 - 7.限制 TextField 输入字符长度
#pragma mark -- TextField代理 -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange: ...
- iOS 限制textField输入的长度
1.电话号码(带3-3-4效果) //指定代理 self.phoneTextField.delegate = self; //当编辑改变的时候,进行字符校验 [self.phoneTextField ...
- iOS 限制TextField输入长度(标准)
iOS 限制TextField输入长度(标准) 网上有很多限制textField输入长度方法,但是我觉得都不是很完美,准确来说可以说是不符合实际开发的要求,因此在这里整理一下textField限制输入 ...
- iOS之限制TextField的输入长度
网上有很多限制textField输入长度方法,但是我觉得都不是很完美,准确来说可以说是不符合实际开发的要求,因此在这里整理一下textField限制输入长度的方法.我所采用的并不是监听方法而是最不同的 ...
- iOS:UITextField中文输入法输入时对字符长度的限制
如题的问题,又是个让我抓狂了大半天的问题,还是做个记录,有与类似问题的同学可参考,但不一定对.具体问题还需具体分析.我遇到的需求是这样的:有一个输入框,输入框内输入文字,文字字数限制在20字. ...
- iOS(Swift) TextField限制输入文本的长度(不是字数)
最近做项目有一个特殊需求,就是需要限制一个TextField的输入文本的长度在一定范围内(注意,不是字数),上网查了一圈没有找到类似文章,这里把我的方法写进来,mark一下: 1.对TextField ...
- 动态SQL字符长度超过8000
动态SQL字符长度超过8000,我记得SQL SERVER 2008中用SP_EXECUTESQL打破了这个限制. 平常用动态SQL,可能都会用EXEC(),但是有限制,就是8000字符串长度.自从S ...
- 解决MVC中JSON字符长度超出限制的异常
解决MVC中JSON字符长度超出限制的异常 解决方法如下: <configuration> <system.web.extensions> <scripting> ...
随机推荐
- 关于PCB布线的顺序到底是怎样才合理?
有人说先布好电源线和地线,让它们尽量靠近走,然后再考虑信号线:也有人说先布好关键的信号线,然后再走电源和地线:还有人说先布好电源线,再布信号线,地线最后布.到底怎么样才算好呢?或者说,一般应按照什么顺 ...
- [Xcode使用 - 2] 设置APP图标和启动画面
1.App Icon 把所有图标文件拖放到 “Images.xcassets” 的”AppIcon” 里面 应对非视网膜和视网膜屏,APP有时会提供两套不同大小的图片,1倍图和2倍图,它们 ...
- 让UILabel具有链接功能,点击后调用safari打开网址
UILabel *labelGovUrl = [[UILabel alloc] initWithFrame:CGRectMake(73.0, 330.0, 180.0, 40.0)]; labelGo ...
- rank() | dense_rank() | row_number() over(PARTITION BY sex order by age desc ) 的区别
1.row_num() over()函数:根据某个字段排序后编号1,2,3.. select *,ROW_NUMBER() over ( order by majorid) as numfrom St ...
- Winform- DotNetBar for Windows Forms的安装的添加
Winform界面不好看,偶尔在网上看到winform的界面美化,对比了一下选择了DotNetBar for Windows Forms 1.破解版网上很多,提供一个参考的下载地址http://dx. ...
- 【UNIX】select、poll、epoll学习
三者都是UNIX下多路复用的内核接口,select是跨平台的接口,poll是systemV标准,epoll是linux专有的接口,基于poll改造而成. select 函数原型: int select ...
- 如何使用validate.js进行动态添加和移除表单验证信息
表单是我们在开当中的常客,那么对表单的验证也是必须的,那么如何实现动态给表单添加验证规则呢? 方法: 1,动态添加验证规则 // 添加$("#addConnectUser").ru ...
- Android ListView快速定位(二)
方法二:android:textFilterEnabled="true" + Filter 这个属性在android.widget.AbsListView下,要求adapter必须 ...
- com.code.servlet
package com.code.servlet; import java.io.IOException; import java.util.LinkedHashMap; import java.ut ...
- js中点击事件方法三种方式的区别
在javascript中,可以为某个元素指定事件,指定的方式有以下三种: 1.在html中,使用onclick属性 2.在javascript中,使用onclick属性 (1)注意函数名没有双引号. ...