想解决问题直接跳转 三、解决UITextField输入限制受中文自动联想影响的问题


一、前言

关于这次需求:UITextField输入限制看起来是个很简单的需求,然而测试还是能测出很多问题,越来越觉得开发时候的UI简直是一个无底洞,问题并不是很难很复杂,但是他总是会在你不可预期的地方突然冒出来。

一点题外话:做了差不多五个月的iOS开发,很惭愧自己还没有接触到深层次一点的内容,接下来要花大概一到两周完成毕业设计,之后可能要找个感兴趣的点去研究一下才行了。


二、UITextField输入限制的基本实现

有两个地方有类似的输入限制需求

A.只支持数字输入,不支持自动联想,限制5位数,输入数字时同一层级的一个按钮title要同时变化

1.首先会想到使用只有数字键盘的样式,即设置UIKeyboardType

试过一两种,参考了其他样式 https://blog.csdn.net/shihuboke/article/details/77430358

发现数字键盘没有带确认/Return/Done健的样式,遂弃用。

最后初始化设置:

//customBtn是TextField的背景按钮,实现点选的效果
self.cmoneyTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, customBtn.frame.size.width, customBtn.frame.size.height)];
self.cmoneyTextField.backgroundColor = [UIColor clearColor];
self.cmoneyTextField.font = [UIFont systemFontOfSize:13.f];
self.cmoneyTextField.textColor = [UIColor colorWithRed:(0x66/255.0) green:(0x66/255.0) blue:(0x66/255.0) alpha:1];
self.cmoneyTextField.textAlignment = NSTextAlignmentCenter;
self.cmoneyTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
self.cmoneyTextField.placeholder = @"其他";
[self.cmoneyTextField setValue:[UIColor colorWithRed:(0x66/255.0) green:(0x66/255.0) blue:(0x66/255.0) alpha:1] forKeyPath:@"_placeholderLabel.textColor"];
self.cmoneyTextField.returnKeyType =UIReturnKeyDone;
self.cmoneyTextField.autocorrectionType = UITextAutocorrectionTypeNo;//关闭自动联想
self.cmoneyTextField.delegate = self;

2.为了只支持数字输入且限制5位数,重写 textField:shouldChangeCharactersInRange:replacementString:方法

这个方法调用的时机是每次文本输入后,文本显示前

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{if (textField == self.cmoneyTextField) {//正则判断 只允许数字输入NSString *checkStr = [textField.text stringByReplacingCharactersInRange:range withString:string];NSString *regex = @"^[0-9]*$";NSPredicate *resultStr = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];if([resultStr evaluateWithObject:checkStr] == NO) {return NO;}if (range.length == 1 && string.length == 0) {return YES;}else if (self.cmoneyTextField.text.length >= 5) {self.cmoneyTextField.text = [textField.text substringToIndex:5];return NO;}}return YES;
}

正则的判断是网上抄的作业,判断了一整串文本,不符合条件就拒绝输入。

第二个判断(range.length == 1 && string.length == 0)可以理解为判断输入是否为删除符。

删除符的原理:个人理解是要在输入时先往文本里面添加一个显示长度为0但是实际算一个长度的占位符,然后在显示时如果遇到删除符则直接删除一个字符,同时删除自身。因此这个判断其实就是为了判断删除符(应该是没有其他的可输入按键有这样的性质,确认键?),避免出现满5位后无法删除的情况。

第三个判断很容易理解了,如果当前已经有5个字符(或以上)了,那么就截剩5个并且拒绝此次输入。

3.接着为了在输入数字后按钮实时变化,监听UITextFieldTextDidChangeNotification通知

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldChange:) name:UITextFieldTextDidChangeNotification object:nil];

收到通知的时机是在文本显示后,实现方法textFieldChange:

- (void)textFieldChange:(NSNotification *)notification
{self.cmoneyCount = [self.cmoneyTextField.text integerValue];if ([self.delegate respondsToSelector:@selector(scriptRewardCategoryView:withCmoney:)]) {[self.delegate scriptRewardCategoryView:self withCmoney:self.cmoneyCount];}
}

这里使用代理方法让外部VC处理按钮变动事件,没有什么难点。

B.支持中英文和数字,支持自动联想,不能超过24个字符,中文算两个字符

上面所说的时机应该很好理解,所以这个需求也差不多。

计算中文字符这个原本就做了封装,同时其实后台也会对输入进行校验,因此我只要实现不超过24个字符的需求就行了。

textField的设置不再赘述,自动联想打开就好。

还是重写 textField:shouldChangeCharactersInRange:replacementString:方法

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{NSMutableString *text = [textField.text mutableCopy];[text replaceCharactersInRange:range withString:string];if (textField == self.nickNameTextField && [text fl_UnicodeLength] > kXXNickNameMaxLength) {char a = [text characterAtIndex:text.length-1];if(a!= 127){return NO;}}return YES;
}

这次简单粗暴很多:直接拿取了输入的文本的最后一位,在长度已经超出的情况下,最后一位如果不是删除符(ascii十进制127)则直接拒绝这次输入(感觉没有A方法的判断好)。


三、解决UITextField输入限制受中文自动联想影响的问题

讲道理上面的东西应该能够完成需求了,但是都在iOS8,9(12没问题,10,11没有测试)上出现了问题

A.关闭了自动联想,但是在输入一个数字后会出现标点符号的自动联想!

上面是iOS8的表现(iPhone6)

上面是iOS12表现(iPhone6Plus 选错了 无影响)

这里注意,点击联想出来的标点符号是可以输入的!

通过打断点可以发现:

iOS8中文联想出来的标点符号输入,不会触发textField:shouldChangeCharactersInRange:replacementString:方法,但是依然能够发出UITextFieldTextDidChangeNotification通知,实在万幸!

解决方法:

收取文本改变通知后再检查并截断一次文本

- (void)textFieldChange:(NSNotification *)notification
{NSString *t = self.cmoneyTextField.text;if(t.length > 0){ //为ios8中文标点联想做特殊处理char lastChar = [t characterAtIndex:t.length-1];if(lastChar < 48 || lastChar > 57){self.cmoneyTextField.text = [t substringToIndex:t.length-1];}}//... 原有代码
}

这里也是很简单粗暴了,以为关闭了自动联想后,输入数字只会出现中文标点符号,且点击后不能继续操作,因此就直接拿最后一个字符判断,如果不是数字就截去。

B.开启了自动联想,但是中文自动联想不触发textField:shouldChangeCharactersInRange:replacementString:方法

其实大概已经可以猜到,iOS8,9的中文联想应该是和之后版本的中文联想有所区别的(还不完善),它们并不归在联想的设置里面,同时也不会触发文本输出的方法,因此需要在接受到文本改变通知之后补救

针对B情况,在iOS8,9会有可以无限输入联想中文的情况(因为不会进入textField:shouldChangeCharactersInRange:replacementString:方法,也就无法判断长度)

解决方法如下

- (void)textFieldChange:(NSNotification *)notification
{NSString *t = self.nickNameTextField.text;if([t fl_UnicodeLength] > kXXNickNameMaxLength) {self.nickNameTextField.text = [t substringToIndex:self.textFieldForAutoMerge];}self.textFieldForAutoMerge = self.nickNameTextField.text.length;
}

同样接受通知调用textFieldChange方法,判断长度并截取。

这里注意使用一个NSInterger变量textFieldForAutoMerge来记录输入前的文本长度,一旦文本显示超过规定,就把前一次输入全部截取。


就这么多,希望第三部分能给大家有所提示

Good Luck Everyone!

【iOS】解决UITextField输入限制受中文自动联想影响的问题相关推荐

  1. ubuntu20.04 微信输入不了中文解决办法

    关于微信的安装,可以看这篇文章: ubuntu 20.04 安装 微信最新方式 安装后发现输入不了中文,这影响我在码代码的时候和妹子聊天啊 ,这可不行,一定要解决掉! 终端输入: cd /opt/de ...

  2. 0.54与0.55版本react-native的TextInput在iOS上无法输入中文日文韩文的bug

    更新最新版本的react-native,发现最近两版本的TextInput终于出现对ios的不友好.在官网查了下发现 0.54与0.55版本react-native的TextInput在iOS上无法输 ...

  3. 在win10 系统输入法 输入几下老是自动被禁用解决办法

    在win10 系统输入法 输入几下老是自动被禁用, 1.尝试换微软输入法,看看是否会出现同样的问题. 可以通过设置>>时间和语言>>区域和语言>>中文>> ...

  4. kali-linux 完美解决sublime输入 中文

    kali-linux 完美解决sublime输入中文 在kali-linux 完成任何一件事情都是非常高兴的,对于长期使用window系统的人是个巨大的挑战. 对于sublime下载后出现不能输入中文 ...

  5. 解决 Linux 下 Sublime Text 中文输入

    2019独角兽企业重金招聘Python工程师标准>>> 完美解决 Linux 下 Sublime Text 中文输入 完美解决 Linux 下 Sublime Text 中文输入 转 ...

  6. Appium 解决不能输入中文字符问题

    Appium 解决不能输入中文字符问题 Appium版本1.3.3以上. Java: 在capabilities中增加两项设置: capabilities.setCapability("un ...

  7. 全面解决amule容易崩溃和中文显示、输入的问题(转)

    全面解决amule容易崩溃和中文显示.输入的问题(转)[@more@] amule是一个类似windows下的emule的ed2k客户端.ed2k是一种类似于Bittorrent的点对点文件传输协议. ...

  8. 解决某些情况下输入法中文状态下输入英文

    解决某些情况下输入法中文状态下输入英文 KB961503是windows 系统的补丁: 文件大小:560.88KB 漏洞影响:安装本更新程序可解决在使用 Windows Live Messenger( ...

  9. Linux系统Deepin/Ubuntu解决IDEA输入中文光标无法跟随的问题

    Linux系统Deepin/Ubuntu解决IDEA输入中文光标无法跟随的问题 1. 问题描述 2. 问题阐述 3. 解决方案 4. 解决步骤[推荐] (1) 先下载资源 (2)解压出jbr,放到一个 ...

  10. sql server 改写与插入的切换键,解决sql输入内容会自动把后面的内容替换掉的问题?

    当我们修改sql语句时,经常会碰到新输入的内容会自动把后面的内容替换掉,问题的关键就在于insert键.ins(insert)键是改写与插入的切换键. 为什么会按到ins(insert)键 1.Del ...

最新文章

  1. ffmpeg库编译加文字_使用ffmpeg库编译错误及解决办法
  2. html制作棋盘,棋盘的制作方法
  3. 软件包管理 rpm yum apt-get dpkg
  4. PHP开发环境配置:安装与配置Apache、PHP、MySQL、PhpMyAdmin
  5. html拖拽模态框,可拖拽的谷歌样式纯javascript模态窗口插件
  6. 介绍自己以及github注册流程
  7. gin框架-2-返回是html格式的网页数据
  8. 【HDU6194】string string string(统计出现k次的子串数目---后缀数组+st表)
  9. 吉林大学超星MOOC学习通高级语言程序设计 C++ 实验01 顺序程序设计(2021级)
  10. JEB工具介绍及使用
  11. UltraEdit 注册机使用激活方法:
  12. 【Alpha版本】冲刺阶段——Day 1
  13. 使用属性在 ASP.NET Web API 2 路由创建一个 REST API
  14. sudo: /etc/sudoers is world writable sudo: no valid sudoers sources found, quitting sudo: 解决方法
  15. tolua, luaframework环境搭建
  16. NIO及多线程实现聊天室完整版
  17. FMC150-两路250Msps AD、两路500Msps DA FMC子卡模块
  18. 如何把excel里面中文小写数字转换成阿拉伯数字
  19. IOS版aplayer使用教程_[按键精灵手机版教程]安卓3.0按键使用教程
  20. AForge.Video.FFMPEG库使用注意事项

热门文章

  1. SpringBoot(53) 整合canal实现数据同步
  2. Multi-Task Feature Learning for Knowledge Graph Enhanced Recommendation
  3. [CVE-2021-45105] Apache Log4j2 漏洞复现与原理详细分析
  4. Visual Paradigm 顾客旅程地图 (Customer Journey Map)
  5. 物联网卡是做什么用的
  6. ROI Pool、ROI Align、PSROI Pool、PrROI Pool
  7. word-目录突然无法更新解决方法
  8. 虚幻引擎5改变了游戏,并与Perforce原生集成
  9. msr830路由器配置虚拟服务器,华三MSR系列路由器(V7)平台家庭宽带配置IPV6
  10. Win10 添加传统照片查看器