2011-01-04 18 views
22

Co staram się osiągnąć jest następująca. Mam NSString ze zdaniem, które ma adres URL w ramach wrażliwości. Jestem potrzebują, aby móc pobrać adres URL, który jest przedstawiony w dowolnej zdaniu, które jest w NSString tak na przykład:Jak wyodrębnić adres URL z zdania znajdującego się w NSString?

powiedzmy miałem ten NSString

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

muszę być w stanie wyodrębnić http://abc.com/efg.php?EFAei687e3EsA od wewnątrz tego NSString. Ten NSString nie jest statyczny i zmieni strukturę, a adres URL niekoniecznie będzie w tym samym miejscu zdania. Próbowałem zajrzeć do kodu trzy20, ale nie ma to dla mnie żadnego sensu. Jak inaczej można to zrobić? Dzięki za pomoc.

+0

Zobacz [moja odpowiedź] (http://stackoverflow.com/a/25574255/1966109) dla podobnego pytania, które wykorzystuje Swift 3 i daje 2 sposoby na rozwiązanie problemu. –

Odpowiedz

20

Edytuj: Mam zamiar wyjść tutaj i powiedzieć, że powinieneś używać NSDataDetector, jak wspomina Dave. Znacznie mniej podatny na błędy niż wyrażenia regularne.


Spójrz na regular expressions. Możesz skonstruować prosty, aby wyodrębnić adres URL za pomocą klasy NSRegularExpression (dostępny tylko na telefonie iPhone, ale ponieważ to właśnie celujesz, wszystko jest w porządku) lub znaleźć taką, z której możesz korzystać. Aby zapoznać się z samouczkiem dotyczącym używania klasy, zobacz here.


Kod chcesz zasadniczo wygląda następująco (przy użyciu John Gruber na super URL regex):

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' 

To będzie wyodrębnić pierwszy URL w dowolny ciąg (oczywiście, to nie sprawdza błędów, więc jeśli ciąg naprawdę nie zawiera żadnych adresów URL nie będzie działać, ale spójrz na klasy NSRegularExpression, aby zobaczyć, jak uzyskać wokół niego

+0

+1 i poprawna odpowiedź !!! Dokładnie tego chciałem i nie wspominając, że było to łatwe do zrealizowania. Dziękuję bardzo za przykładowy kod A ++. Działa bez zarzutu !!! – 0SX

+0

Świetnie! Cieszę się, że to działało dla ciebie. –

+0

Świetna odpowiedź ... –

2

potrzebne są dwie rzeczy:.

  1. Kategoria, która dodaje wyrażenie do ciągu NSString (tj. RegexKit)
  2. Matching Regex for URLS.

pozdrowienia,

+0

+1 Dzięki, bardzo pomogłem. – 0SX

+0

@ 0SX, należy użyć REGEX i dopasowanego schematu gruber dla adresów URL. To najlepszy sposób na uzyskanie podciągu URL. –

+0

Zrobię, jeszcze raz dziękuję Cesar! – 0SX

2

Funny wspomnieć three20, że było to pierwsze miejsce, miałem zamiar pójść poszukać odpowiedzi. Oto metoda z 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; 
      } 
     } 
    } 
} 

każdym razem robi [self addNode:node]; po pierwszym if części, to dodanie znaleziony URL. To powinno zacząć! Mam nadzieję że to pomoże. :)

+0

+1 Dzięki, próbowałem poszukać tego kodu, ale zrezygnowałem. Dziękuję bardzo za kod. – 0SX

+0

Oczywiście, jeśli kompilujesz dla iPhone'a, nie ma powodu, aby używać takiego zawiłego kodu zamiast klasy 'NSRegularExpression'. –

3

użycie tego

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]; 

} 
+0

+1 Dzięki za kod, to faktycznie działa również, ale w formacie tablicy, który może być przydatny dla niektórych rzeczy :-) Jeszcze raz dziękuję. – 0SX

85

Użyć 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); 
    } 
} 

W ten sposób nie trzeba polegać na zawodnej wyrażeń regularnych, jak i firmy Apple uaktualnia swój kod detekcji link otrzymujesz te ulepszenia za darmo.

+1

+1 Niesamowite !!! Nie wiedziałem, że to był kod wykrywania linków dla NSDataDetector. Cóż, właśnie nauczyłem się czegoś nowego. Dzięki Dave, będę musiał przetestować zarówno wyrażenie regularne, jak i kod NSDataDector, aby zobaczyć, które najlepiej pasuje do moich potrzeb. Jednak jestem z tobą na temat raczej za pomocą kodu Apple niż nierzetelny kod. Dzięki jeszcze raz. Być może będę musiał zmienić moją odpowiedź. :-) – 0SX

+1

@ 0SX Nie ma za co. Tylko zastrzeżenie: działa tylko na iOS 4+ –

+1

jest naprawdę dobre, zamiast używać wyrażenia regularnego. – Tirth

4

Zastosowanie takiego:

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); 

    } 
}]; 

ten wypisze wszystkie linki w someString jeden po drugim

1

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) 
} 

Source

+0

Błędne zgłoszenie tutaj. proszę, niech ktoś odda głos z powrotem! To działa! –

1

Korzystanie Swift 2.2 - NSDataDetector

+0

nie ma nic złego w tej odpowiedzi, testowałem ponownie i działa idealnie !!!!! – KarimIhab

+1

Zgadzam się, a następnie wykryłem błąd w moich danych źródłowych. To działa, przepraszam! –

Powiązane problemy