Detect URL in NSString

I'm currently using a UITextView in a UITableViewCell in order to make links clickable, but this is giving very poor performance.

So I was wondering if it's possible to detect links in a NSString and if there is a link, use the UITextView, otherwise just use a UILabel.

Answers


Absolutely. Use NSDataDetector (NSDataDetector Class Reference)


I guess you are familiar with regexes to detect URLs, so in order to get one or the other type of view in your cell, you can simply return two different UITableViewCells from your tableView:cellForRowAtIndexPath: method.

It could look like this (please notice, typed in the browser not tested):

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSString *dataString = // Get your string from the data model

    // Simple pattern found here: http://regexlib.com/Search.aspx?k=URL
    NSString *URLpattern = @"^http\\://[a-zA-Z0-9\-\.]+\\.[a-zA-Z]{2,3}(/\\S*)?$";

    NSError *error = NULL;
    NSRegularExpression *URLregex = [NSRegularExpression regularExpressionWithPattern:URLpattern
                                                                              options:NSRegularExpressionCaseInsensitive
                                                                                error: &error];

    NSUInteger numberOfMatches = [URLregex numberOfMatchesInString:string
                                                    options:0
                                                      range:NSMakeRange(0, [string length])];

    if ( numberOfMatches == 0 ) {
        static NSString *PlainCellIdentifier = @"PlainCellIdentifier";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
        }
        cell.textLabel.text = timeZoneWrapper.localeName;
    }
    else {
        static NSString *FancyCellIdentifier = @"FancyCellIdentifier";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
        }

        // Configure cell view with text view here
    }

    return cell;
}

Using this snip of code you would be able to find and get http url in UILable using NSDataDetector:

NSDataDetector* detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
                NSArray* matches = [detector matchesInString:yourString options:0 range:NSMakeRange(0,  [yourString. length])];
                NSLog(@"%@",matches) ;
                NSMutableAttributedString *MylabelAttributes = 
    [[NSMutableAttributedString alloc] initWithString:yourString];
                for (int index = 0 ; index < matches.count; index ++) {
                NSTextCheckingResult *textResult = [matches objectAtIndex : index]; 
                NSTextCheckingType textResultType = textResult.resultType;
                NSRange testRange = textResult.range;
                NSURL *testUrl = textResult.URL ;}

After applying this code, you will be able to attribute your `UILabel` text:

    [MylabelAttributes addAttribute:NSLinkAttributeName value:testUrl  range: testRange];
    [MylabelAttributes addAttribute:NSFontAttributeName                       
    value:[UIFont boldSystemFontOfSize:7.0]range:NSMakeRange(0,yourString.length)];

Need Your Help

argument types of undocumented Objective-C methods in Instruments (OSX)

objective-c macos

Is there a way to determine the argument types of Objective-C methods traced by Instruments?