How can I extract a URL from a sentence that is in a NSString?

冷暖自知 提交于 2019-11-28 04:33:12

Edit: I'm going to go out on a limb here and say you should probably use NSDataDetector as Dave mentions. Far less prone to error than regular expressions.


Take a look at regular expressions. You can construct a simple one to extract the URL using the NSRegularExpression class (only available on iPhone, but since that's what you're targeting, you're ok), or find one online that you can use. For a tutorial on using the class, see here.


The code you want essentially looks like this (using John Gruber's 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'

That will extract the first URL in any string (of course, this does no error checking, so if the string really doesn't contain any URL's it won't work, but take a look at the NSRegularExpression class to see how to get around it.

Use an 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);
  }
}

This way you don't have to rely on an unreliable regular expression, and as Apple upgrades their link detection code, you get those improvements for free.

Use Like This:

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

     }
 }];

This will Output the all links in your someString one by one

use this

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

}

you need two things:

  1. A category that adds regex to NSString (i.e. RegexKit)
  2. Matching Regex for URLS.

regards,

Funny you mention three20, that was the first place I was going to go look for the answer. Here's the method from 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;
            }
        }
    }
}

Every time it does [self addNode:node]; after the first if part, it's adding a found URL. This should get you started! Hope this helps. :)

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

Using 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)
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!