Улучшить алгоритм поиска URL-адресов в теле текста - obj-c - PullRequest
1 голос
/ 29 декабря 2010

Я пытаюсь придумать алгоритм для поиска URL-адресов в тексте. В настоящее время у меня есть следующий код (это был мой сижу и взломать код, и я знаю, что должен быть лучший способ):

    statusText.text = @"http://google.com http://www.apple.com www.joshholat.com";

NSMutableArray *urlLocations = [[NSMutableArray alloc] init];

NSRange currentLocation = NSMakeRange(0, statusText.text.length);
for (int x = 0; x < statusText.text.length; x++) {
    currentLocation = [[statusText.text substringFromIndex:(x + currentLocation.location)] rangeOfString:@"http://"];
    if (currentLocation.location > statusText.text.length) break;
    [urlLocations addObject:[NSNumber numberWithInt:(currentLocation.location + x)]];
}
currentLocation = NSMakeRange(0, statusText.text.length);
for (int x = 0; x < statusText.text.length; x++) {
    currentLocation = [[statusText.text substringFromIndex:(x + currentLocation.location)] rangeOfString:@"http://www."];
    if (currentLocation.location > statusText.text.length) break;
    [urlLocations addObject:[NSNumber numberWithInt:(currentLocation.location + x)]];
}
currentLocation = NSMakeRange(0, statusText.text.length);
for (int x = 0; x < statusText.text.length; x++) {
    currentLocation = [[statusText.text substringFromIndex:(x + currentLocation.location)] rangeOfString:@" www." options:NSLiteralSearch];
    if (currentLocation.location > statusText.text.length) break;
    [urlLocations addObject:[NSNumber numberWithInt:(currentLocation.location + 1 + x)]];
}

//Get rid of any duplicate locations
NSSet *uniqueElements = [NSSet setWithArray:urlLocations];
[urlLocations release];
NSArray *finalURLLocations = [[NSArray alloc] init];
finalURLLocations = [uniqueElements allObjects];

//Parse out the URLs of each of the locations
for (int x = 0; x < [finalURLLocations count]; x++) {
    NSRange temp = [[statusText.text substringFromIndex:[[finalURLLocations objectAtIndex:x] intValue]] rangeOfString:@" "];
    int length = temp.location + [[finalURLLocations objectAtIndex:x] intValue];
    if (temp.location > statusText.text.length) length = statusText.text.length;
    length = length - [[finalURLLocations objectAtIndex:x] intValue];
    NSLog(@"URL: %@", [statusText.text substringWithRange:NSMakeRange([[finalURLLocations objectAtIndex:x] intValue], length)]);
}

Я чувствую, что это можно улучшить с помощью регулярных выражений или чего-то еще. Любая помощь в улучшении этого будет принята с благодарностью.

Ответы [ 2 ]

5 голосов
/ 29 декабря 2010

Если вы нацелены на iOS 4.0+, вы должны позволить Apple сделать всю работу за вас и использовать встроенные детекторы данных. Создайте экземпляр NSDataDetector с параметром NSTextCheckingTypeLink и запустите его над строкой. Документация для NSDataDetector содержит несколько хороших примеров использования класса.

Если вы по какой-либо причине не используете / не можете использовать детекторы данных, Джон Грубер опубликовал хороший шаблон регулярных выражений для обнаружения URL несколько месяцев назад: http://daringfireball.net/2010/07/improved_regex_for_matching_urls

1 голос
/ 30 декабря 2010

В качестве продолжения мой код был изменен на:

    statusText.text = @"http://google.com http://www.apple.com www.joshholat.com hey there google.com";

NSError *error = NULL;
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:&error];

NSArray *matches = [detector matchesInString:statusText.text
                                     options:0
                                       range:NSMakeRange(0, statusText.text.length)];

for (NSTextCheckingResult *match in matches) {
    if ([match resultType] == NSTextCheckingTypeLink) {
        NSLog(@"URL: %@", [[match URL] absoluteURL]);
    }
}
...