【问题标题】:Adding a constant country code at beginning of UITextField在 UITextField 的开头添加一个常量国家代码
【发布时间】:2015-01-14 11:29:53
【问题描述】:

我有一个 UITextField,用户需要在其中输入电话号码。

这就是现在的样子:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    // Auto-add hyphen before appending 4rd or 7th digit
    //
    //
    if (range.length == 0 && (range.location == 3 || range.location == 7))
    {
        textField.text = [NSString stringWithFormat:@"%@-%@", textField.text, string];
        return NO;
    }

    // Delete hyphen when deleting its trailing digit
    //
    //
    if (range.length == 1 && (range.location == 4 || range.location == 8))
    {
        range.location--;
        range.length = 2;
        textField.text = [textField.text stringByReplacingCharactersInRange:range withString:@""];
        return NO;
    }

    //  Prevent crashing undo bug – see note below.
    //
    //
    if (range.length + range.location > textField.text.length)
    {
        return NO;
    }

    //  Limit text field characters
    //
    //
    NSUInteger newLength = [textField.text length] + [string length] - range.length;
    return (newLength > 12) ? NO : YES;
}

在第 3 位数字之后,我添加了一个连字符,然后又添加了一个连字符。我在这里想要实现的是在UITextField 的开头添加一个国家代码作为常量,并且用户将无法删除它。假设是美国国家代码,那么 UITextField 文本将在开头 +1- 时看起来像这样,然后在写完完整数字后,它将看起来像这样:+1-600-242-252

我该怎么做?

提前致谢!

【问题讨论】:

    标签: ios objective-c iphone uitextfield


    【解决方案1】:

    此答案假定起始国家代码字符串在末尾包含连字符,例如:self.countryCode = @"+1-";。文本字段最初应包含“+1-”。

    我的回答方式比您最初的意图更全面,因为它可以处理您忽略的许多用例,例如具有多个字符的复制和粘贴操作、不适当的连字符删除、不适当的连字符添加、中线插入、等等。但它仍然不完美,因为您的原始答案在某些方面是不具体的......例如,如果您指定用户应该只能输入数字,那么代码可以更清晰。

    下面的实现在贯穿始终的 cmets 中逐行描述。

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        // Combine the new text with the old
        NSMutableString *combinedText = [[textField.text stringByReplacingCharactersInRange:range withString:[NSString stringWithFormat:@"%@", string]] mutableCopy];
    
        // If the user deletes part of the country code or tries
        // to edit it in any way, don't allow it
        if (combinedText.length < self.countryCode.length ||
            ![combinedText hasPrefix:self.countryCode]) {
            return NO;
        }
    
        //  Limit text field characters to 12
        if (combinedText.length > self.countryCode.length + 12) {
            return NO;
        }
    
        // If the user tries to add a hyphen where there's supposed
        // to be a hyphen, allow them to do so.
        if ([string isEqualToString:@"-"] &&
            (range.location == self.countryCode.length + 3 ||
            range.location == self.countryCode.length + 7)) {
            return  YES;
        }
    
        // Remove all the hyphens other than the one directly
        // following the country code        
        [combinedText replaceOccurrencesOfString:@"-" withString:@"" options:0 range:NSMakeRange(self.countryCode.length, [combinedText length] - self.countryCode.length)];
    
        // Auto-add the hyphens before the 4th and 7th digits
        if (combinedText.length > self.countryCode.length + 3)
            [combinedText insertString:@"-" atIndex:self.countryCode.length + 3];
        if (combinedText.length > self.countryCode.length + 7)
            [combinedText insertString:@"-" atIndex:self.countryCode.length + 7];
    
        // Store the original cursor position
        UITextPosition *pos = [textField selectedTextRange].start;
    
        // Count up the original number of hyphens
        NSUInteger originalNumberOfHyphens = [[textField.text componentsSeparatedByString:@"-"] count] - 1;
        // Count up the new number of hyphens
        NSUInteger newNumberOfHyphens = [[combinedText componentsSeparatedByString:@"-"] count] - 1;
    
        // Create a cursor offset to reflect the difference
        // in the number of hyphens
        float offset = newNumberOfHyphens - originalNumberOfHyphens;
    
        // Update the text field to contain the combined text
        textField.text = combinedText;
    
        // Update the cursor position appropriately
        if (string.length > 0) {
            UITextPosition* cursor = [textField positionFromPosition:[textField beginningOfDocument] offset:range.location + range.length + offset + string.length];
            textField.selectedTextRange = [textField textRangeFromPosition:cursor toPosition:cursor];
        } else {
            UITextPosition* cursor = [textField positionFromPosition:pos inDirection:UITextLayoutDirectionLeft offset:1-offset];
            textField.selectedTextRange = [textField textRangeFromPosition:cursor toPosition:cursor];
        }
    
        // No need to replace the string since it's already been done
        return NO;
    }
    

    【讨论】:

    • @JesseOnolememen 我刚刚再次测试了这段代码,它对我有用....你能解释一下“它仅限于 2 个字符 + 国家代码”是什么意思吗
    • 起初,您只能在国家代码旁边输入 2 个字符,但我设法弄明白了。我正在使用 swift,所以这只是导致问题的转换错误。现在完美运行。 @lyndsetscott
    【解决方案2】:

    要在开头保持一个常量,您基本上是想检查该常量是否仍然存在于建议的文本中。如果它不拒绝此类编辑。

    您不应尝试在特定的编辑步骤中插入连字符。最好操纵整个字符串。

    例如

    1. 测试字符串是否有效。即starts with +1
    2. 删除您之前添加的所有连字符
    3. 重新插入所有连字符

    在代码中如下所示:

    - (void)viewDidLoad {
        [super viewDidLoad];
        self.textField.text = @"+1"; // start with a +1 in the textField otherwise we can't change the field at all
    }
    
    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
        NSString *proposedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
    
        if (![proposedText hasPrefix:@"+1"]) {
            // tried to remove the first +1
            return NO;
        }
        NSString *formattedPhoneNumber = [proposedText substringFromIndex:2]; // without +1 prefix
        NSString *unformattedPhoneNumber = [formattedPhoneNumber stringByReplacingOccurrencesOfString:@"-" withString:@""]; // without hypens
    
        // start with the prefix
        NSMutableString *newText = [NSMutableString stringWithString:@"+1"];
    
        for (NSInteger i = 0; i < [unformattedPhoneNumber length]; i++) {
            if (i % 3 == 0) {
                // add a - every 3 characters. add one at the beginning as well
                [newText appendString:@"-"];
            }
            // add each digit from the unformatted phonenumber
            [newText appendString:[unformattedPhoneNumber substringWithRange:NSMakeRange(i, 1)]];
        }
        textField.text = newText;
        return NO;
    }
    

    这仍然是一个非常幼稚的实现。它有几个问题,例如光标总是在末尾,因为我们手动设置了 textField 的text。所以用户不能轻易删除字符串中间的数字。当然有办法解决这个问题。 selectedTextRange 将是要使用的属性。而且您不能真正将电话号码粘贴到该字段中。当然,用户不能删除连字符。

    在用户键入时进行格式化往往会很快变得复杂,因为存在很多边缘情况。但这应该让你开始。

    【讨论】:

    • 请记住,尽管最后一个分组是连续 4 个数字...在您当前的代码中,它会将这些数字错误地分组,例如。 +1-675-973-874-2。而且它不会停在 12 位数,因为你还没有处理过......
    • 而且我相信 selectedTextRange 仅适用于 UITextViews
    猜你喜欢
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-19
    • 2018-10-16
    • 2021-11-26
    • 1970-01-01
    • 2013-06-13
    相关资源
    最近更新 更多