2011-01-04 8 views
22

Quello che sto cercando di realizzare è il seguente. Ho una NSString con una frase che ha un URL all'interno della sensibilità. Sto bisogno di essere in grado di afferrare l'URL che si presenta all'interno di qualsiasi frase che si trova a NSString così per esempio:Come posso estrarre un URL da una frase che si trova in una NSString?

Diciamo che ho avuto questa NSString

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

ho bisogno di essere in grado di estrarre http://abc.com/efg.php?EFAei687e3EsA dall'interno di quella NSString. Questo NSString non è statico e cambierà la struttura e l'url non si troverà necessariamente nello stesso punto della frase. Ho provato a guardare nel codice del codice 20 ma non ha senso per me. In quale altro modo può essere fatto? Grazie per l'aiuto.

+0

Vedere [risposta] (http://stackoverflow.com/a/25574255/1966109) per una domanda simile che utilizza Swift 3 e offre 2 modi per risolvere il problema. –

risposta

20

Modifica: Ho intenzione di uscire su un arto qui e dire che probabilmente dovresti usare NSDataDetector come menziona Dave. Molto meno incline all'errore rispetto alle espressioni regolari.


Dai uno sguardo allo regular expressions. Puoi costruirne uno semplice per estrarre l'URL usando la classe NSRegularExpression (disponibile solo su iPhone, ma dal momento che è quello che stai targeting, sei ok), o trovarne uno online che puoi usare. Per un'esercitazione sull'uso della classe, vedere here.


Il codice che si desidera in sostanza si presenta così (di con John Gruber 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' 

che estrae il primo URL a qualsiasi stringa (naturalmente, questo non fa il controllo degli errori, quindi se la stringa in realtà non contiene alcun URL non funzionerà, ma date un'occhiata alla classe NSRegularExpression per vedere come arrivare intorno ad esso

+0

+1 e risposta corretta !!! Questo è esattamente quello che volevo e per non dire che era facile da implementare. Grazie mille per il codice di esempio A ++. Funziona perfettamente !!! – 0SX

+0

Ottimo! Sono contento che ha funzionato per te. –

+0

Gran risposta ... –

2

avete bisogno di due cose:.

  1. Una categoria che aggiunge regex a NSString (ad es. RegexKit)
  2. Matching Regex for URLS.

saluti,

+0

+1 Grazie, ho aiutato molto. – 0SX

+0

@ 0SX, assicurarsi di utilizzare REGEX e lo schema di corrispondenza di gruber per gli URL. Questo è il modo migliore per ottenere la sottostringa dell'URL. –

+0

Lo faremo, grazie ancora Cesar! – 0SX

2

divertente si menzionano Three20, che è stato il primo posto che stavo per andare a cercare la risposta. Ecco il metodo da 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; 
      } 
     } 
    } 
} 

Ogni volta che lo fa [self addNode:node]; dopo la prima if parte, è l'aggiunta di una trovata URL. Questo dovrebbe farti cominciare! Spero che questo ti aiuti. :)

+0

+1 Grazie, ho provato a cercare quel codice ma mi sono arreso. Grazie mille per il codice. – 0SX

+0

Ovviamente, se si compila per l'iPhone, non c'è motivo di usare un codice contorto come questo invece della classe 'NSRegularExpression'. –

3

uso questo

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 Grazie per il tuo codice, funziona anche in questo caso ma in un formato array che potrebbe essere utile per alcune cose :-) Grazie ancora. – 0SX

85

Utilizzare un 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); 
    } 
} 

In questo modo non c'è bisogno di fare affidamento su un'espressione regolare inaffidabile, e in quanto Apple aggiorna il codice di rilevamento di collegamento, ottieni questi miglioramenti gratuitamente.

+1

+1 Impressionante !!! Non sapevo che fosse un codice di rilevamento del collegamento per NSDataDetector. Bene, ho appena imparato qualcosa di nuovo. Grazie a Dave, dovrò testare sia l'espressione regolare che il tuo codice NSDataDector per vedere quale sia la soluzione migliore per le mie esigenze. Comunque, io sono con te riguardo piuttosto che usare il codice di Apple piuttosto che codice inaffidabile. Grazie ancora. Potrei dover cambiare la mia risposta. :-) – 0SX

+1

@ 0SX prego. Solo un avvertimento: funziona solo su iOS 4+ –

+1

è davvero buono invece di usare espressioni regolari. – Tirth

4

Usa in questo modo:

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

    } 
}]; 

Questa volontà di uscita del tutti i link nel vostro someString uno per uno

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

Discendente errato qui. per favore qualcuno up-votare di nuovo! Funziona! –

1

Utilizzando 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) 
    } 
} 
+0

non c'è niente di sbagliato in questa risposta, l'ho provato di nuovo e funziona perfettamente !!!!! – KarimIhab

+1

Ho downvoted questo e poi ho trovato un errore nei miei dati di origine. Funziona, scusa! –

Problemi correlati