iOS NSString使用正则表达式检测链接和电子邮件

时间:2016-09-15 22:12:55

标签: ios objective-c regex nsstring

我已经对我的问题有了答案,但我想知道是否有更好的方法来做到这一点。

目前,我使用以下内容检测NSString中的链接和电子邮件:

    NSString *teststring = @"this has a link http://google.com/232&q=23%67fg and an email admin007.info@yahoo.com in the sentence";
    NSString *linkregex = @"(http|ftp|https)://([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?";
    NSPredicate *linkpredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", linkregex];
    NSString *emailregex = @"^([a-zA-Z0-9_\\-\\.]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$";
    NSPredicate *emailpredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailregex];

    NSArray *arrayofwords = [teststring componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    arrayofwords = [arrayofwords filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]];

    for (NSString *word in arrayofwords) {
        if ([linkpredicate evaluateWithObject: word]){
            NSLog(@"Matches link regex: %@",word);
        }

        if ([emailpredicate evaluateWithObject: word]){
            NSLog(@"Matches email regex: %@",word);
        }
    }

这可以打印出来:

Matches link regex: http://google.com/232&q=23%67fg
Matches email regex: admin007.info@yahoo.com

我想知道是否有办法避免创建临时数组arrayofwords?正则表达式是否可以在整个句子中找到正则表达式的所有匹配?如果我有非常长的句子(将整个文件读作NSString),那么临时的单词方式会导致缓慢。 我不确定这是一个"正则表达式"问题或更多的iOS问题?

1 个答案:

答案 0 :(得分:0)

用户使用NSDataDetector向我的问题发布了更好的解决方案,但似乎他们删除了解决方案。我测试了它,它在我的场景中完美运行,所以我在这里发布。如果他们再次发布,请在下面发表评论,我会接受他们的解决方案。

[self detectType:@"this has a link http://google.com/232&q=23%67fg and an email admin007.info@yahoo.com in the sentence"];



-(void)detectType:(NSString*)stringToUse{
    NSError *error;
    NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes: NSTextCheckingTypeLink error:&error];

    if (!error && detector) {
        [detector enumerateMatchesInString:stringToUse options:0 range:NSMakeRange(0, stringToUse.length) usingBlock:^(NSTextCheckingResult * __nullable result, NSMatchingFlags flags, BOOL *stop){

            NSString *type;
            NSString *matched = [stringToUse substringWithRange:result.range];

            // Type checking can be eliminated since it is used for logging only.
            if (result.resultType==NSTextCheckingTypeLink) {
                if ([matched rangeOfString:@"@"].length) {
                    type = @"Email";
                }else{
                    type = @"Link";
                }
            } else {
                type = @"Unknown";
            }

            NSLog(@"Matched %@: %@",type,matched);
        }];
    } else {
        NSLog(@"%@",error.description);
    }
}