10

The easiest way I can explain this problem is with a code sample and its output, but essentially what's happening is NSDataDetector is detecting a phone number within a string that includes the words "phone number".

NSError *error = nil;
NSDataDetector *dataDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber
                                                               error:&error];

NSArray *stringsToTest = @[
                           @"testing phone number 0123 4567891",
                           @"testing some other number 0123 4567892",
                           @"phone number 0123 4567893",
                           @"blah blah 0123 4567894",
                           @"testing telephone number 0123 4567895"
                           ];

for (NSString *string in stringsToTest)
{
    [dataDetector enumerateMatchesInString:string
                                   options:0
                                     range:NSMakeRange(0, string.length)
                                usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
                                    NSLog(@"%@", result.phoneNumber);
                                }];
}

Output:

2013-11-24 19:04:26.000 PhoneNumberDetector[21874:70b] phone number 0123 4567891
2013-11-24 19:04:26.000 PhoneNumberDetector[21874:70b] 0123 4567892
2013-11-24 19:04:26.000 PhoneNumberDetector[21874:70b] phone number 0123 4567893
2013-11-24 19:04:26.000 PhoneNumberDetector[21874:70b] 0123 4567894
2013-11-24 19:04:26.001 PhoneNumberDetector[21874:70b] 0123 4567895

I've read the documentation and searched around SO but can't find anything that indicates if this is the intended behaviour and, if so, why.

This happens on the 7.0 simulator as well as my iPhone 5s running 7.0.4.

If anyone can shed any light on this issue I'd greatly appreciate it.

Update: To clarify, I don't want the text "phone number" to be part of the result when accessing the NSTextCheckingResult phoneNumber property.

Alex Zavatone
  • 4,106
  • 36
  • 54
Steve Wilford
  • 8,894
  • 5
  • 42
  • 66
  • Is that the actual log for those inputs? Can you change the source numbers so you can see exactly what results match. I'm not aware of any documentation covering this, question is how you want to deal with it. – Wain Nov 24 '13 at 20:07
  • Yep that output is correct, I've edited the numbers to help show matches (1,2,3,4,5). – Steve Wilford Nov 25 '13 at 08:37
  • it's a strange behavior of ios 7 ,you have to report on apple site. – Dhaval Bhadania Nov 25 '13 at 10:34
  • Bug report filed at bugreport.apple.com and Open Radar http://openradar.appspot.com/15561004 – Steve Wilford Nov 30 '13 at 11:57
  • I'm not sure whether it is a bug or on purpose, but I have a related question whose current solution depends upon this behavior, so I'd be sort of sad if it is a bug that gets fixed: http://stackoverflow.com/questions/24880007/detect-the-access-code-portion-of-a-conference-call-phone-number-in-an-nsstrin – benvolioT Jul 22 '14 at 06:21
  • It seems Apple has fixed this, now the `result.phoneNumber` contains only the numbers. But there is another issue: when you try to detect a string contains only a pure phone number which can be detected in a prefixed string (eg "phone number 10086" results 10086), this pure phone number may NOT be detected properly. I mean "phone number 10086" results "10086", yet "10086" results nil. I also met the same issue on "tel", "phone" prefix, just like "phone number". – Elf Sundae Aug 25 '19 at 18:58

1 Answers1

5

While it does seem that this is a bug in Apple's code, there is a simple workaround if you want to extract just the number from the string by eliminating the non-numeric characters within a block:

NSError *error = nil;
    NSDataDetector *dataDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber
                                                                   error:&error];

    NSArray *stringsToTest = @[
                                @"testing phone number 0123 4567891",
                                @"testing some other number 0123 4567892",
                                @"phone number 0123 4567893",
                                @"blah blah 0123 4567894",
                                @"testing telephone number 0123 4567895",
                                @"phone",
                                @"number",
                                @"my phone number 1234587985",
                                @"this string does not contain a phone number"
                               ];

    for (NSString *string in stringsToTest)
    {
        [dataDetector enumerateMatchesInString:string
                                       options:0
                                         range:NSMakeRange(0, string.length)
                                    usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) 
                                    {
                                        NSString *numberWithExtra = result.phoneNumber;
                                        NSCharacterSet *toRemove = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
                                        NSString *trimmed = [[numberWithExtra componentsSeparatedByCharactersInSet:toRemove] componentsJoinedByString:@""];
                                        if(trimmed && trimmed.length)
                                        {
                                            NSLog(@"%@", trimmed);
                                        }
                                        else
                                        {
                                            NSLog(@"No phone number");
                                        }
                                    }];
    }
Alex Zavatone
  • 4,106
  • 36
  • 54
Adrian
  • 71
  • 3