Как я могу извлечь URL из предложения, которое находится в строке NSString? - PullRequest
23 голосов
/ 04 января 2011

Я пытаюсь сделать следующее. У меня есть строка NSString с предложением, в котором есть URL-адрес. Мне нужно иметь возможность получить URL-адрес, который представлен в любом предложении, которое находится внутри строки NSString, например:

Допустим, у меня была эта строка NSString

NSString *someString = @"This is a sample of a http://abc.com/efg.php?EFAei687e3EsA sentence with a URL within it.";

Мне нужно иметь возможность извлечь http://abc.com/efg.php?EFAei687e3EsA из этой строки NSString. Эта строка NSString не является статичной и будет изменять структуру, и URL-адрес не обязательно будет находиться в том же месте предложения. Я пытался заглянуть в код Three20, но для меня это не имеет смысла. Как еще это можно сделать? Спасибо за помощь.

Ответы [ 8 ]

89 голосов
/ 04 января 2011

Используйте NSDataDetector:

NSString *string = @"This is a sample of a http://abc.com/efg.php?EFAei687e3EsA sentence with a URL within it.";
NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:string options:0 range:NSMakeRange(0, [string length])];
for (NSTextCheckingResult *match in matches) {
  if ([match resultType] == NSTextCheckingTypeLink) {
    NSURL *url = [match URL];
    NSLog(@"found URL: %@", url);
  }
}

Таким образом, вам не нужно полагаться на ненадежное регулярное выражение, и когда Apple обновляет свой код обнаружения ссылок, вы получаетеэти улучшения бесплатно.

21 голосов
/ 04 января 2011

Редактировать: Я собираюсь выйти здесь на конечность и сказать, что вы, вероятно, должны использовать NSDataDetector, как упоминает Дейв. Гораздо менее подвержен ошибкам, чем регулярные выражения.


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


Код, который вы хотите, по сути выглядит следующим образом (используя регулярное выражение супер URL Джона Грубера ):

NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:@"(?i)\\b((?:[a-z][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))" options:NSRegularExpressionCaseInsensitive error:NULL];
NSString *someString = @"This is a sample of a http://abc.com/efg.php?EFAei687e3EsA sentence with a URL within it.";
NSString *match = [someString substringWithRange:[expression rangeOfFirstMatchInString:someString options:NSMatchingCompleted range:NSMakeRange(0, [someString length])]];
NSLog(@"%@", match); // Correctly prints 'http://abc.com/efg.php?EFAei687e3EsA'

Это извлечет первый URL в любой строке (конечно, это не проверяет ошибки, поэтому, если строка действительно не содержит никаких URL, она не будет работать, но взглянем на класс NSRegularExpression, чтобы посмотрим, как обойти это.

5 голосов
/ 18 апреля 2014

Используйте как это:

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

[detector enumerateMatchesInString:someString
                           options:0
                             range:NSMakeRange(0, someString.length)
                        usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
 {
     if (result.resultType == NSTextCheckingTypeLink)
     {
         NSString *str = [NSString stringWithFormat:@"%@",result.URL];
         NSLOG(%@,str);

     }
 }];

Это выведет все ссылки в вашем someString по одной

3 голосов
/ 04 января 2011

используйте это

NSURL *url;
    NSMutableArray *listItems = [[someString componentsSeparatedByString:@" "] mutableCopy];

for(int i=0;i<[listItems count];i++)
{
    NSString *str=[listItems objectAtIndex:i];
      if ([str rangeOfString:@"http://"].location == NSNotFound)
          NSLog(@"Not url");
      else 
        url=[NSURL URLWithString:str];  

}
2 голосов
/ 04 января 2011

Забавно, вы упомянули три20, это было первое место, куда я собирался пойти, чтобы найти ответ.Вот метод из Three20:

- (void)parseURLs:(NSString*)string {
    NSInteger index = 0;
    while (index < string.length) {
        NSRange searchRange = NSMakeRange(index, string.length - index);
        NSRange startRange = [string rangeOfString:@"http://" options:NSCaseInsensitiveSearch
                             range:searchRange];
        if (startRange.location == NSNotFound) {
            NSString* text = [string substringWithRange:searchRange];
            TTStyledTextNode* node = [[[TTStyledTextNode alloc] initWithText:text] autorelease];
            [self addNode:node];
            break;
        } else {
            NSRange beforeRange = NSMakeRange(searchRange.location, startRange.location - searchRange.location);
            if (beforeRange.length) {
                NSString* text = [string substringWithRange:beforeRange];
                TTStyledTextNode* node = [[[TTStyledTextNode alloc] initWithText:text] autorelease];
                [self addNode:node];
            }

            NSRange searchRange = NSMakeRange(startRange.location, string.length - startRange.location);
            NSRange endRange = [string rangeOfString:@" " options:NSCaseInsensitiveSearch
                             range:searchRange];
            if (endRange.location == NSNotFound) {
                NSString* URL = [string substringWithRange:searchRange];
                TTStyledLinkNode* node = [[[TTStyledLinkNode alloc] initWithText:URL] autorelease];
                node.URL = URL;
                [self addNode:node];
                break;
            } else {
                NSRange URLRange = NSMakeRange(startRange.location,
                                         endRange.location - startRange.location);
                NSString* URL = [string substringWithRange:URLRange];
                TTStyledLinkNode* node = [[[TTStyledLinkNode alloc] initWithText:URL] autorelease];
                node.URL = URL;
                [self addNode:node];
                index = endRange.location;
            }
        }
    }
}

Каждый раз, когда он делает [self addNode:node]; после первой части if, он добавляет найденный URL.Это должно начать вас!Надеюсь это поможет.:)

2 голосов
/ 04 января 2011

вам нужно две вещи:

  1. Категория, которая добавляет регулярное выражение к NSString (т.е. RegexKit)
  2. Соответствующее регулярное выражение для URL .

С уважением,

1 голос
/ 02 мая 2016

Использование Swift 2.2 - NSDataDetector

let string = "here is the link www.google.com"
let types: NSTextCheckingType = [ .Link]
let detector = try? NSDataDetector(types: types.rawValue)
detector?.enumerateMatchesInString(string, options: [], range: NSMakeRange(0, (string as NSString).length)) { (result, flags, _) in
    if(result?.URL != nil){
        print(result?.URL)
    }
}
1 голос
/ 27 марта 2016

Swift 2:

let input = "This is a test with the URL https://www.hackingwithswift.com to be detected."
let detector = try! NSDataDetector(types: NSTextCheckingType.Link.rawValue)
let matches = detector.matchesInString(input, options: [], range: NSMakeRange(0, input.characters.count))

for match in matches {
    let url = (input as NSString).substringWithRange(match.range)
    print(url)
}

Источник

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...