验证iOS手机号码

28

我需要验证一个国际电话号码。

我知道验证国际电话号码很困难,所以我会保持简单:

+或00,然后6-14个数字

我目前使用的正则表达式代码出了一些问题,我无法解决。它只是说无法打开正则表达式并崩溃。

这是我目前的代码:

NSString *phoneRegex = @"^[\+(00)][0-9]{6,14}$";
NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", phoneRegex];

BOOL phoneValidates = [phoneTest evaluateWithObject:phoneNumber];

我错在哪里了?

谢谢!


相关链接:https://dev59.com/PHVD5IYBdhLWcg3wQJKT#41982 https://dev59.com/om445IYBdhLWcg3wDV8P#5933940 - Mick MacCallum
谢谢 - 这就是为什么我保持简单的原因。API调用将完全验证它,我只想尽可能限制调用次数。 - Thomas Clayson
相关的,我认为更好的答案在这里:http://stackoverflow.com/questions/17063278 - Guillaume Algis
最好的方法是这个 - meaning-matters
9个回答

40
NSString *phoneRegex = @"^((\\+)|(00))[0-9]{6,14}$";

这种方式更好。如果您转义“\”符号,您的代码也可以正常工作。


反斜杠(\)是为了转义加号(+)...那我还需要转义加号吗? - Thomas Clayson
1
你需要先转义斜杠才能在字符串中“输入”。\ 将会在正则表达式中表示为 \。 - whiteagle
1
但这仅适用于遵循ITU建议的国家。日本,美国和其他一些国家使用不同的前缀。我想知道您的代码是否无法为这些国家提供支持?如果是这样,请修改您的代码以接受各种前缀,而不仅仅是00。http://en.wikipedia.org/wiki/List_of_international_call_prefixes - Pavan
2
为什么这里需要括号,使用 @"^(\\+|00)[0-9]{6,14}$"; 不是同样好吗? - turingtested

16

复制粘贴方法验证电话号码:

- (BOOL)validatePhone:(NSString *)phoneNumber
{
    NSString *phoneRegex = @"^((\\+)|(00))[0-9]{6,14}$";
    NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", phoneRegex];

    return [phoneTest evaluateWithObject:phoneNumber];
}

验证电话号码的开源库,或开源

https://github.com/iziz/libPhoneNumber-iOS


1
能否使用像这个链接提供的电话验证库?非常完整并提供了许多服务。 - GuillaumeS

2

这取决于你想要多严格。看起来这个正则表达式并不是特别严格。这个正则表达式的意思是:

从行首开始匹配 匹配一个加号+(也许是1或0,这似乎有点含糊不清,但根据实现情况可能不是),因为捕获括号:()打破了+和?之间的关系 可能放错位置的: 匹配任何数字0-9,出现1次或0次,重复6-14次 然后匹配一个数字0-9 最后匹配行尾。 此外,需要注意任何反斜杠都必须加倍... @"\b" 表示单词边界。你可以尝试一些类似的东西...

@"\\b[\\d]{3}\\-[\\d]{3}\\-[\\d]{4}\\b"
would I think match your example, but it wouldn't match
(555) 555 - 5555 or
555.555.5555 or
+44 1865  55555

我不确定我理解了。你是从另一个答案中复制的吗? - Thomas Clayson
@vikramjain 如果电话号码中有字母,我们该如何解析它?比如苹果公司的电话号码是1800MYAPPLE。有没有相应的正则表达式呢? - Pradip Vanparia

2
验证电话号码的唯一好方法是使用Google的神奇LibPhoneNumber。有一个iOS端口,或者您可以在隐藏的UIWebView中运行JavaScript实现。
(我几年前就用过后者,当时还没有iOS端口。即使在旧的iPhone上也非常快速,效果很好。)

我认为那是一个好建议,但问题具体是关于如何让一段代码工作的。我曾经处理过特定的验证部分,我们有狭窄的要求,使用库会过度。 - benc
@benc 一段“代码片段”由于电话号码的复杂性而总是会失败。除了使用库之外,没有其他方法。快速查看主要资源文件LibPhoneNumber应该会立即使您信服。 - meaning-matters
我已经测试了不止几个电话号码处理程序,我不需要太多的说服。但有时候,即使它是最好的解决方案,询问的人也无法使用它。 - benc
@benc,这不是好和更好的问题,而是正确和不正确的问题。当然,提问者可以选择使用不正确的电话号码格式并惹恼用户。 - meaning-matters

2

NSString *phoneRegex = @"^((\\+)|(00))[0-9]{6,14}|[0-9]{6,14}$";

这是经过测试的正则表达式,可以接受带国家代码或不带国家代码的电话号码。


注意,这会在iOS 15中崩溃。 - DrMickeyLauer

1

txtlpmobile.text是一个字符串(你将要输入的手机号码)。

 int length = [self getLength:txtLpMobile.text];
            if(length == 10) {
                if(range.length == 0)
                    return NO;
            }
            if(length == 3){
                NSString *num = [self formatNumber:txtLpMobile.text];
                txtLpMobile.text = [NSString stringWithFormat:@"(%@) ",num];

                if(range.length > 0) {
                    txtLpMobile.text = [NSString stringWithFormat:@"%@",[num substringToIndex:3]];

                }
            } else if(length == 6) {
                NSString *num = [self formatNumber:txtLpMobile.text];
                txtLpMobile.text = [NSString stringWithFormat:@"(%@) %@-",[num  substringToIndex:3],[num substringFromIndex:3]];
                if(range.length > 0) {
                    txtLpMobile.text = [NSString stringWithFormat:@"(%@) %@",[num substringToIndex:3],[num substringFromIndex:3]];
                }
            }

            NSUInteger newLength;
            newLength = [txtLpMobile.text length] + [string length] - range.length;
            NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS_ONLY] invertedSet];
            NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
            return (([string isEqualToString:filtered])&&(newLength <= CHARACTER_LIMIT));

用于格式化数字

-(NSString*)formatNumber:(NSString*)mobileNumber
{
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"(" withString:@""];
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@")" withString:@""];
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@" " withString:@""];
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"-" withString:@""];
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"+" withString:@""];

    int length = [mobileNumber length];
    if(length > 10)
    {
        mobileNumber = [mobileNumber substringFromIndex: length-10];
    }
    return mobileNumber;
}

获取长度
-(int)getLength:(NSString*)mobileNumber
{
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"(" withString:@""];
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@")" withString:@""];
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@" " withString:@""];
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"-" withString:@""];
    mobileNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"+" withString:@""];

    int length = [mobileNumber length];

    return length;
}

不支持国际电话号码。 - meaning-matters

0
在Swift 4中 -
func ValidateMobileNumber(txtFeid : UITextField, strChk : String, range: NSRange) -> Bool {

    if txtFeid.text!.count >= 10 {
        return false
    } 

    let formatePre = "^((\\+)|(00))[0-9]{6,14}$"
    let resultPredicate : NSPredicate = NSPredicate(format: "SELF MATCHES %@",formatePre)
    return resultPredicate.evaluate(with: strChk)
}

0

验证电话号码和密码限制的简单方法,只需按照以下步骤操作。

if ((self.mobileTxtFld.text.length < 10 )) {
    [_mobileTxtFld becomeFirstResponder];
}
else if ((self.passwordTxtFld.text.length < kPasswordCharacterMinLimit) || (self.passwordTxtFld.text.length > kPasswordCharacterMaxLimit)) {
    // show alert
}

之后,您可以在文本字段代理方法“shouldChangeCharactersInRange”中实现此代码:

if (textField == _mobileTxtFld) {
    if([string rangeOfCharacterFromSet:ALLOWED_NUMBERS].location == NSNotFound){
        NSUInteger newLength = [textField.text length] + [string length] - range.length;
        if(newLength > kMobileNumberLimit - 1){
            if(textField.text.length != kMobileNumberLimit){
                textField.text  = [NSString stringWithFormat:@"%@%@",textField.text,string];
            }
            [textField resignFirstResponder];
            return NO;
        }
        else{
            return YES;
        }
    }
    else{
        return NO;
    }
}

return YES;

这里的ALLOWED_NUMBERS和kMobileNumberLimit是

#define kMobileNumberLimit 10
#define ALLOWED_NUMBERS [[NSCharacterSet decimalDigitCharacterSet] invertedSet]
#define minLimit 6
#define maxLimit 17

-4
-(int)findLength:(NSString*)phoneNumber
{
    phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:@"(" withString:@""];
    phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:@")" withString:@""];
    phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:@" " withString:@""];
    phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:@"-" withString:@""];
    phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:@"+" withString:@""];

int length = [phoneNumber length];

return length;

}


1
欢迎来到Stack Overflow!这个问题已经有一个答案并被接受(4年前)!你的回答是否带来了新的东西?如果是,你应该解释一下为什么。 - alexbt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接