iOS UITextField 长串数字每隔3位添加空格显示(一)

下面所示方法,TextField是禁用了复制、粘贴、剪切等操作的
如果需要保留复制、粘贴、剪切等操作且保证字符串每隔3位添加空格显示,请看
iOS UITextField 长串数字每隔3位添加空格显示(二)

整体思路

  • 1. 先只考虑无空格时光标的变化。比如 输入字符时,光标位置+1,删除时,光标位置-1
  • 2.计算光标位置前的空格数,进而获取到带空格的光标位置。此光标位置即光标的最终位置。光标最终位置 = 无空格光标前空格数 + 无空格变化后的光标位置
  • 3.原始字符串添加空格

示例:
比如 当前文本为123☐|45, 其中 | 表示光标,☐表示空格,即 123后有个空格,光标在空格后。此时用户输入数字6。

1.获取不带空格的光标位置,即 当前光标位置-当前光标位置前的空格数,当前光标位置为4,当前光标位置前的空格数为1,即不带空格的光标位置为3
123|45
2.获取变化后的不带空格光标位置,即不带空格的光标位置+1,为4
1236|45
3.计算变化后的带空格光标位置,即变化后不带空格光标位置+变化后不带空格光标位置前的需要显示的空格数。1236 需要显示一个空格,则变化后的光标位置为5
4.原始字符串添加空格
即 123☐645
变化后的光标位置为5,即123☐6|45

上代码

// 核心代码

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    // 限制表情输入
    if ([string emo_containsEmoji]) {
        return NO;
    }
    
    // 限制非数字 和 字符串长度限制
    NSString * toBeString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    
    NSUInteger wordCountlimit = 19;
    NSString *wordLimitString = kNumbers;
    if (toBeString.length > wordCountlimit) {
        return NO;
    }
    
    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:wordLimitString] invertedSet];
    NSString * filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
    BOOL basicTest = [string isEqualToString:filtered];
    if(!basicTest) {
        return NO;
    }
    
    // 设置textfiled text 和 光标位置
    if (string.length > 0) {
        [self handleTextFieldAddEvent:string];
    }else{
        [self handleTextFieldDeleteEvent];
    }
    [self checkJoinBtnStatus];
    return NO;
}

- (void)handleTextFieldAddEvent:(NSString *)numStr {
    // 思路
    /*
      1. 计算不带‘ ’的字符串的光标 A
      2. 计算不带‘ ’的字符串 变化后的光标B  B = A +1
      3. 计算带‘ ’的字符串 变化后的光标C 光标C是通过截取到光标B的字符串中含有‘ ’的个数来计算的
    */
    
    NSString *placeholder = @" ";
    
    // 变化前
    // 1.获取当前光标信息
    NSRange currentTextRange = [self.meetingNumTextFiled selectedRange];
    NSInteger rangeLength = currentTextRange.length;
    //当前带空格的Text
    NSString *currentTextString = self.meetingNumTextFiled.text;
    
    // 2.获取不带占位符的光标
    NSString *subCursorCurrentString = [self.meetingNumTextFiled.text substringToIndex:currentTextRange.location];
    NSInteger spaceCount = [[subCursorCurrentString mutableCopy] replaceOccurrencesOfString:placeholder withString:@"" options:NSLiteralSearch range:NSMakeRange(0, subCursorCurrentString.length)];
    NSRange noSpaceCurrentRange = NSMakeRange(currentTextRange.location-spaceCount, rangeLength);
    
    // 3.当前 不带占位符的Text
    NSString *noSpaceCurrentTextString = [currentTextString stringByReplacingOccurrencesOfString:placeholder withString:@""];
    
    // 变化后
    // 1.变化后 不带占位符的Text的range
    NSRange noSpaceChangedRange = NSMakeRange(noSpaceCurrentRange.location+numStr.length, rangeLength);
    
    
    // 2.变化后 不带空格的Text
    NSMutableString *tempStringm = [[NSMutableString alloc] initWithString:noSpaceCurrentTextString];
    [tempStringm insertString:numStr atIndex:noSpaceCurrentRange.location];
    NSString *noSpaceChangedTextString = [tempStringm mutableCopy];
    
    
    // 3.变化后 带占位符的Text 的range
    NSString * noSpaceSubCursorChangedString  = [noSpaceChangedTextString substringToIndex:noSpaceChangedRange.location];
    
    // 计算光标前占位符个数
    long subCursorChangedSpaceCount = 0;
    if (noSpaceSubCursorChangedString.length >= 1) {
        subCursorChangedSpaceCount = (noSpaceSubCursorChangedString.length -1) / 3;
    }
    
    NSRange changedTextRange = NSMakeRange(noSpaceChangedRange.location+subCursorChangedSpaceCount, rangeLength);
    
    // 4.变化后 带占位符的Text
    NSMutableString *muStr = [noSpaceChangedTextString mutableCopy];
    if (muStr.length >3) {
        int i=2;
        while (i<muStr.length) {
            if ((i+1)%4==0) {
                [muStr insertString:placeholder atIndex:i];
            }
            i++;
        }
    
    }
    self.meetingNumTextFiled.text = muStr;
    
       dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
        //必须加延迟,否则无法更新光标位置
        [self.meetingNumTextFiled setSelectedRange:changedTextRange];
    });
}

- (void)handleTextFieldDeleteEvent {
    
    /*
      1. 计算不带‘-’的字符串的光标 A
      2. 计算不带‘-’的字符串 变化后的光标B  B = A -1
      3. 计算带‘-’的字符串 变化后的光标C 光标C是通过截取到光标B的字符串中含有‘-’的个数来计算的
    */
    
    NSString *placeholder = @" ";
    
    // 变化前
    // 1.获取当前光标信息
    NSRange currentTextRange = [self.meetingNumTextFiled selectedRange];
    NSInteger rangeLength = currentTextRange.length;
    //当前带空格的Text
    NSString *currentTextString = self.meetingNumTextFiled.text;
    
    // 2.获取不带占位符的光标
    NSString *subCursorCurrentString = [self.meetingNumTextFiled.text substringToIndex:currentTextRange.location];
    NSInteger spaceCount = [[subCursorCurrentString mutableCopy] replaceOccurrencesOfString:placeholder withString:@"" options:NSLiteralSearch range:NSMakeRange(0, subCursorCurrentString.length)];
    NSRange noSpaceCurrentRange = NSMakeRange(currentTextRange.location-spaceCount, rangeLength);
    
    // 3.当前 不带占位符的Text
    NSString *noSpaceCurrentTextString = [currentTextString stringByReplacingOccurrencesOfString:placeholder withString:@""];
    
    // 变化后
    // 1.变化后 不带占位符的Text的range
    if (noSpaceCurrentRange.location<1) {
        return ;
    }
    NSRange noSpaceChangedRange = NSMakeRange(noSpaceCurrentRange.location-1, rangeLength);
    
    
    // 2.变化后 不带空格的Text
    NSMutableString *tempStringm = [[NSMutableString alloc] initWithString:noSpaceCurrentTextString];
    
    NSInteger deleteLocation = (NSInteger)noSpaceChangedRange.location;
    deleteLocation = (deleteLocation > 0 ? deleteLocation : 0);
    if (tempStringm.length-1>=deleteLocation) {
       [tempStringm deleteCharactersInRange:NSMakeRange(deleteLocation, 1)];
    }
    
    NSString *noSpaceChangedTextString =  [tempStringm mutableCopy];
    
    
    // 3.变化后 带占位符的Text 的range
    NSString * noSpaceSubCursorChangedString  = [noSpaceChangedTextString substringToIndex:noSpaceChangedRange.location];
    
    // 计算光标前占位符个数
    long subCursorChangedSpaceCount = 0;
    if (noSpaceSubCursorChangedString.length >= 1) {
        subCursorChangedSpaceCount = (noSpaceSubCursorChangedString.length -1) / 3;
    }
    
    NSRange changedTextRange = NSMakeRange(noSpaceChangedRange.location+subCursorChangedSpaceCount, rangeLength);
    
    // 4.变化后 带占位符的Text
    NSMutableString *muStr = [noSpaceChangedTextString mutableCopy];
    if (muStr.length >3) {
        int i=2;
        while (i<muStr.length) {
            if ((i+1)%4==0) {
                [muStr insertString:placeholder atIndex:i];
            }
            i++;
        }
    
    }
    self.meetingNumTextFiled.text = muStr;
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
        //必须加延迟,否则无法更新光标位置
        [self.meetingNumTextFiled setSelectedRange:changedTextRange];
    });
}
// UITextField+ExtentRange

- (NSRange)selectedRange {
    
    UITextPosition* beginning = self.beginningOfDocument;
    
    UITextRange* selectedRange = self.selectedTextRange;
    UITextPosition* selectionStart = selectedRange.start;
    UITextPosition* selectionEnd = selectedRange.end;
    
    const NSInteger location = [self offsetFromPosition:beginning toPosition:selectionStart];
    const NSInteger length = [self offsetFromPosition:selectionStart toPosition:selectionEnd];
    
    return NSMakeRange(location, length);
}

- (void)setSelectedRange:(NSRange)range {
    UITextPosition* beginning = self.beginningOfDocument;
    
    UITextPosition* startPosition = [self positionFromPosition:beginning offset:range.location];
    UITextPosition* endPosition = [self positionFromPosition:beginning offset:range.location + range.length];
    UITextRange* selectionRange = [self textRangeFromPosition:startPosition toPosition:endPosition];
    [self setSelectedTextRange:selectionRange];
}

设置textfield的selectedTextRange需在设置textfield的text后,不然光标会一直在文本最后

目前不支持粘贴
可禁用UITextfield的复制粘贴功能

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容