我想要完成的工作如下。我有一个NSString,其中一个句子在感知中有一个URL。我需要能够获取NSString中任何句子中显示的URL,例如:
假设我有这个NSString
NSString *someString = @"This is a sample of a http://abc.com/efg.php?EFAei687e3EsA sentence with a URL within it.";
我需要能够从该NSString中提取http://abc.com/efg.php?EFAei687e3EsA。这个NSString不是静态的,并且将改变结构,并且url不一定在句子的同一位置。我试着调查三个代码,但对我来说没有意义。怎么办呢?谢谢你的帮助。
答案 0 :(得分:89)
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升级其链接检测代码时,您可以免费获得这些改进。
答案 1 :(得分:21)
编辑:我打算在这里走出去,说你应该像Dave提到的那样使用NSDataDetector
。比正则表达式更容易出错。
看看regular expressions。您可以使用NSRegularExpression类构建一个简单的URL来提取URL(仅适用于iPhone,但由于这是您的目标,您可以),或者在线找到一个可以使用的URL。有关使用该课程的教程,请参阅here。
您想要的代码基本上是这样的(使用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'
这将提取任何字符串中的第一个URL(当然,这不会进行错误检查,因此如果字符串确实不包含任何URL,则它将无效,但请查看NSRegularExpression
上课了解如何绕过它。
答案 2 :(得分:5)
像这样使用:
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 :(得分:3)
使用此
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];
}
答案 4 :(得分:2)
你需要两件事:
的问候,
答案 5 :(得分:2)
有趣的是你提到了three20,这是我第一次去寻找答案。这是来自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
{{1}},它都会添加找到的网址。这应该让你开始!希望这可以帮助。 :)
答案 6 :(得分:1)
斯威夫特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)
}
答案 7 :(得分:1)
使用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)
}
}
答案 8 :(得分:0)
Swift 4.x
Xcode 12.x
let string = "This is a test with the URL https://www.hackingwithswift.com to be detected. www.example.com"
let types: NSTextCheckingResult.CheckingType = [ .link]
let detector = try? NSDataDetector(types: types.rawValue)
detector?.enumerateMatches(in: string, options: [], range: NSMakeRange(0, (string as NSString).length)) { (result, flags, _) in
if(result?.url != nil){
print(result?.url)
}
}