Usando NSRegularExpression per estrarre URL su iPhone

Sto usando il seguente codice sulla mia app per iPhone, presa da qui per estrarre tutti gli URL dal codice .html con striping.

Sono solo in grado di estrarre il primo URL, ma ho bisogno di un array che contiene tutti gli URL. Il mio NSArray non restituisce NSStrings per ciascun URL, ma solo le descrizioni degli oggetti.

Come faccio a rendere il mio arrayOfAllMatches restituire tutti gli URL, come NSStrings?

 -(NSArray *)stripOutHttp:(NSString *)httpLine { // Setup an NSError object to catch any failures NSError *error = NULL; // create the NSRegularExpression object and initialize it with a pattern // the pattern will match any http or https url, with option case insensitive NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?" options:NSRegularExpressionCaseInsensitive error:&error]; // create an NSRange object using our regex object for the first match in the string httpline NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])]; NSArray *arrayOfAllMatches = [regex matchesInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])]; // check that our NSRange object is not equal to range of NSNotFound if (!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) { // Since we know that we found a match, get the substring from the parent string by using our NSRange object NSString *substringForFirstMatch = [httpLine substringWithRange:rangeOfFirstMatch]; NSLog(@"Extracted URL: %@",substringForFirstMatch); NSLog(@"All Extracted URLs: %@",arrayOfAllMatches); // return all matching url strings return arrayOfAllMatches; } return NULL; 

}

Ecco il mio output NSLog:

 Extracted URL: http://example.com/myplayer All Extracted URLs: ( "{728, 53}{ http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}", "{956, 66}{ http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}", "{1046, 63}{ http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}", "{1129, 67}{ http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)? 0x1}" ) 

Il metodo corrisponde matchesInString:options:range: restituisce una matrice di oggetti NSTextCheckingResult . È ansible utilizzare l’enumerazione rapida per scorrere l’array, estrarre la sottostringa di ogni corrispondenza dalla stringa originale e aggiungere la sottostringa a un nuovo array.

 NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?" options:NSRegularExpressionCaseInsensitive error:&error]; NSArray *arrayOfAllMatches = [regex matchesInString:httpLine options:0 range:NSMakeRange(0, [httpLine length])]; NSMutableArray *arrayOfURLs = [[NSMutableArray alloc] init]; for (NSTextCheckingResult *match in arrayOfAllMatches) { NSString* substringForMatch = [httpLine substringWithRange:match.range]; NSLog(@"Extracted URL: %@",substringForMatch); [arrayOfURLs addObject:substringForMatch]; } // return non-mutable version of the array return [NSArray arrayWithArray:arrayOfURLs]; 

Prova NSDataDetector

 NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil]; NSArray *matches = [linkDetector matchesInString:text options:0 range:NSMakeRange(0, [text length])]; 

Con NSDataDetector usando Swift:

 let types: NSTextCheckingType = .Link var error : NSError? let detector = NSDataDetector(types: types.rawValue, error: &error) var matches = detector!.matchesInString(text, options: nil, range: NSMakeRange(0, count(text))) for match in matches { println(match.URL!) } 

Utilizzando Swift 2.0:

 let text = "http://www.google.com. http://www.bla.com" let types: NSTextCheckingType = .Link let detector = try? NSDataDetector(types: types.rawValue) guard let detect = detector else { return } let matches = detect.matchesInString(text, options: .ReportCompletion, range: NSMakeRange(0, text.characters.count)) for match in matches { print(match.URL!) } 

Utilizzando Swift 3.0

 let text = "http://www.google.com. http://www.bla.com" let types: NSTextCheckingResult.CheckingType = .link let detector = try? NSDataDetector(types: types.rawValue) let matches = detector?.matches(in: text, options: .reportCompletion, range: NSMakeRange(0, text.characters.count)) for match in matches! { print(match.url!) } 

per ottenere tutti i collegamenti da una determinata stringa

 NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:@"(?i)\\b((?:[az][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][az]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”'']))" options:NSRegularExpressionCaseInsensitive error:NULL]; NSString *someString = @"www.facebook.com/link/index.php This is a sample www.google.com of a http://abc.com/efg.php?EFAei687e3EsA sentence with a URL within it."; NSArray *matches = [expression matchesInString:someString options:NSMatchingCompleted range:NSMakeRange(0, someString.length)]; for (NSTextCheckingResult *result in matches) { NSString *url = [someString substringWithRange:result.range]; NSLog(@"found url:%@", url); } 

Mi sono ritrovato così nauseato dalla complessità di questa semplice operazione (“abbinare TUTTE le sottostringhe”) che ho creato una piccola libreria che sto umilmente chiamando Unsuck che aggiunge un po ‘di NSRegularExpression a NSRegularExpression sotto forma di metodi from e allMatches . Ecco come li useresti:

 NSRegularExpression *re = [NSRegularExpression from: @"(?i)\\b(https?://.*)\\b"]; // or whatever your favorite regex is; Hossam's seems pretty good NSArray *matches = [re allMatches:httpLine]; 

Si prega di controllare il codice sorgente non registrato su github e dimmi tutte le cose che ho fatto di sbagliato 🙂

Si noti che (?i) rende la distinzione maiuscole e minuscole quindi non è necessario specificare NSRegularExpressionCaseInsensitive .