美文网首页iOS开发技能提升iOS学习开发iOS点点滴滴
TextField 输入身份证号手机号银行卡号格式化解决方案

TextField 输入身份证号手机号银行卡号格式化解决方案

作者: ac986bb0e59a | 来源:发表于2017-11-22 00:57 被阅读121次

    问题描述

    TextField中输入身份证号,手机号,银行卡号时每隔几位需要添加空格。当输入错误时需要从末尾或者中间删除,删除之后还要保持当前textfield的中内容保持每隔几位就有一个空格的格式。这篇文章主要是为了解决这个问题

    ==解决上面的问题主要要解决两个点:==

    • [ ] 光标的位置
    • [ ] 空格的位置

    上面的两种情况又可以分为:

    • 从最后一位删除
    • 从中间删除
    • 一次删除一个和多个
    • 从最后一位添加
    • 从中间添加
    • 一次添加一位和多位

    这几种情况都要考虑光标的位置和空格的位置,每次添加和删除都要重新计算.

    实现:

    首先详细说下👇的这个代理方法:

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    
    range

    shouldChangeCharactersInRange :有location 和length 两个参数
    location 是即将被替代的内容的位置
    length 是即将被替代的内容的长度

    string

    用来替代在range位置内容的字符串

    • [x] 假如:textfield中有内容为1234

    三种情况解释下string 和range参数 :

    1. 光标在最后一位时删除一位 :那么string就是为空 range的location 就是光标前面的内容的下标即为3 length就是1 表示被删除的内容长度为1 ,结果是string占据了range表示的位置 即123,3后面的4被空字符串占据了即被删除了
    2. 光标在最后一位删除两位:操作,长按textfield选中23,点击删除。可以发现string依旧为空 ,range变为 location=1, length=2 即位置在下标为1 长度为2的字符串被空字符串替代了,还剩1,所谓的23被删除了
    3. 添加一个:光标在最后一位。输入一个2,此时range:location为1,length为0 即被替代的内容位置在下标为1的地方,长度是空。string为2,那么结果就是一个下标为1,长度为0的字符串被string替代了,即textfield内容添加了一个2,复制到textfield中的内容range 和 string 也是同样的适用

    说的这么详细主要为下一步做准备。

    UITextInput协议 中的几个属性和方法

    设置光标的位置需要下面的两个方法

    
    // 获取以fromPosition为基准偏移offset的光标位置。
    - (nullable UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset;
    // 创建一个UITextRange
    - (nullable UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition;
    
    
    • [x] 设置光标位置的方法

    根据UITextInput协议的两个方法可以得出设置光标的位置的方法

    + (void)setCursorLocation:(UITextField *)textField withOffset:(NSInteger) offset{
        // offset 光标要所处的位置
        // 生成新的postion
        UITextPosition *newPostion = [textField positionFromPosition:textField.beginningOfDocument offset:offset] ;
        //设置光标 从一个点到另外一个点如果两个点一样 那么光标就在这个点
        textField.selectedTextRange = [textField textRangeFromPosition:newPostion toPosition:newPostion];
    }
    

    ==注意==:在textField中,有一个属性称之为selectedTextRange,这个属性为UITextRange类型,包含[start,end)两个值,通过实验可以发现,在没有文字被选取时,start 和 end的值一样 代表当前光标的位置;当有区域被选择时,start和end分别是选择的头和尾的光标位置

    可以看出 setCursorLocation 方法中很重要的一个参数是偏移量

    • [x] 添加空格的方法
    // 在指定的位置添加空格
    +(NSString*)insertString:(NSString*)string withBlankLocations:(NSArray<NSNumber *>*)locations {
        if (!string) {
            return nil;
        }
        NSMutableString* mutableString = [NSMutableString stringWithString:[string stringByReplacingOccurrencesOfString:@" " withString:@""]];
        for (NSNumber *location in locations) {
            if (mutableString.length > location.integerValue) {
                [mutableString insertString:@" " atIndex:location.integerValue];
            }
        }
        return  mutableString;
    }
    

    上面这个方法是根据传入的空格的位置,遍历整个字符串,在指定的位置为字符串添加一个空格. 这个方法调用的时机就是 textField 中的 text 发生改变时调用,比如说删除或者增加字符串

    ++那么以下就根据不同的情况来计算偏移量设置光标 和 添加空格++

    删除字符串

    如何判断是点击了键盘的删除

    如上面所说 在

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    

    这个代理方法中 当string为空时就是删除。range是一个位置表示string的位置 如果string为空时 range.length 表示删除的长度

    1. 删除一位
      如果 range.length == 1
      如果string 为空 且 range的location 为当前textField.text的长度减一 即location是textField.text的最后一个字符时 表示在最后一位删除

    ① 如果在最后一位删除一位不需要设置光标的位置和添加空格

    ② 如果不是最后一位删除一位则要判断删除的是不是空格。如果是空格则会连续删除两次

    // 不是最后一位
                            NSInteger locationOffset = range.location;
                            if (range.location < text.length && [text characterAtIndex:range.location] == ' ' && [textField.selectedTextRange isEmpty]) {
                                [textField deleteBackward]; // 删除空格
                                locationOffset --;
                            }
                            [textField deleteBackward];// 删除空格前面的字符
    

    上面的代码调用了两次[textField deleteBackward] 删除了两次

    此时需要修改空格的位置和光标的位置,偏移量 offset 就是 range.location 的值 ,每删除一位 offset 就要减1

    1. 删除多位
      同删除一位的逻辑一样 string为空切 range.length > 1 就表示一次删除多位

    ① 是否是在最后一位开始删除,如果再最后一位开始删除那么仍然不需要设置光标的位置,但是需要设置空格的位置

    ② 如果不是最后一位开始删除,则需要计算光标的位置,偏移量仍然是当前 range.location

    添加字符串

    如何判断是添加?

    如上面所说 在

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    

    这个代理方法中 当string不为空时就是添加。range是一个位置表示string的位置 如果string不为空时 range.length 表示添加的字符串的长度

    如果所输入的字符串长度还没有超出限制则直接添加到 textField 中然后在预定的位置添加空格

    // 添加到textField 中 这个方法是 UIKeyInput 协议中的方法
    [textField insertText:string];
    //textField中的字符串发生变化需要重新设置空格
    textField.text = [self insertString:textField.text withBlankLocations:blankLocation];
    

    此时要计算偏移量 ,在计算是光标的位置是 range.location + string.length ,但是如果在光标位置出正好有空格则offset需要 +1 如下

    NSInteger offset = range.location + string.length;
                
                for (NSNumber *location in blankLocation) {
                    if (range.location == location.integerValue) {
                        offset ++;
                    }
                }
                [self setCursorLocation:textField withOffset:offset];
    

    通过以上几种情况就可以解决文章开头描述的问题了.

    Demo 在这里
    我是 Demo

    转载请注明出处 http://www.jianshu.com/p/5175402109d5 谢谢!

    如果解决了您的问题,请点赞支持下哈!

    相关文章

      网友评论

      本文标题:TextField 输入身份证号手机号银行卡号格式化解决方案

      本文链接:https://www.haomeiwen.com/subject/vnggvxtx.html