自己的项目中一直有一个必现的UITextField退格变清空问题,测试发现只有iOS6下有,其它iOS版本都没有问题,基本上可以确定与iOS6有关。由于问题不是很大又忙就搁置了很久,今天实在不能忍受便花了点时间解决此问题,记录一下吧。
这个问题是在某个有默认值的UITextField上是必现的,一旦用退格键删除最后一个字符或中间某个字符,整个UITextfield的内容被清空了,一直百思不得其解,google了一下发现有人遇到类似的问题,并给出了复现步骤(链接),如下:
有一个secureTextEntry为Yes的UITextField和 一个普通的UITextField,重现步骤:
1. 点击普通的UITextField输入类容,
2. 点击密码UITextField输入内容,
3. 点击普通的UITextField重新获得焦点,
4. 接着点击键盘上的退格键,
结果:这时会发现普通的UITextField被清空了。
测试了一下,随便找一个有用户名与密码登录页面的应用,在iOS6下就会复现出这个问题,比如iPhone自带的邮件app。但这个重现步骤说得并不准确,第1步和第2步的前提是对应的UITextField已经有内容,虽然跟自己的复现方法有点不一样,不过总算知道这个问题是怎么回事了。怎么说呢,这应该是iOS6的UITextField的一个新特性引入的问题,原文把这个问题称之为“iOS 6 Secure密码UITextField造成非密码UITextField退格清空Bug”,但是iOS6.0就有这个问题,iOS6.1.3都没有解决,估计apple没把它当bug,坑爹啊。
咱们拿apple没办法,那就只有想办法绕过去啊,初步的思路是截获退格键删除行为,每点一次退格键删除时只允许删除一个字符。这就要用到UITextFieldDelegate的一个textField:shouldChangeCharactersInRange:replacementString方法,这个方法是在UITextField的内容改变时调用,第二个参数表明内容改变的范围,第三个参数是替代的字符串。代码如下:
1 2 3 4 5 6 7 8 9 |
|
设置一下UITextField的delegate就可以调用到此方法,range.length == 1 && string.length == 0就是删除一个字符时所满足的条件,如果条件满足,就只让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 |
|
思路是先取到光标位置,把文本内容暂存,清空原来UITextField的内容,然后将暂存的文本内容中光标左侧的文字replace掉重新赋给UITextField,并恢复光标位置,难点在于怎么获取光标位置与恢复光标位置。
一般用到用户名与密码UITextField的地方用这个方法就能解决问题了,只是还有点小问题,即如果不是从中间删除一个字符,而是一次删除若干个字符还是有问题的,这是由if中的range.length == 1条件限制的,稍加改造下应该就能解决。另外一个问题是如果有中文字符或其它UTF8字符,估计得考虑一下是不是应该要用“text.length – 1”,不过能有多少应用的用户名或密码带中文呢