6

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.

Monolo
  • 18,205
  • 17
  • 69
  • 103
woutr_be
  • 9,532
  • 24
  • 79
  • 129
  • Might be you can check for 'http' in NSString, if it contains then it is link. – rishi Jun 13 '12 at 08:58
  • @rishi, the problem is that there are many types of urls, UITextView seems to detect them all, so google.com, www.google.com, ... – woutr_be Jun 13 '12 at 09:07

3 Answers3

16

Absolutely. Use NSDataDetector (NSDataDetector Class Reference)

Community
  • 1
  • 1
quellish
  • 21,123
  • 4
  • 76
  • 83
2

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;
}
Monolo
  • 18,205
  • 17
  • 69
  • 103
  • 1
    I'm not really familiar with regexes, especially not in objective-c, hence the question here – woutr_be Jun 13 '12 at 09:02
  • Thanks for the example, would there be a difference between using 2 custom cells, or just use one, but add the UITextView and UILabel in it and then remove one of them? – woutr_be Jun 13 '12 at 09:32
  • Yeah, I just added them in IB and removed them with code, in my case I would've to do a check anyway to set the row height – woutr_be Jun 13 '12 at 09:43
1

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)];
Atishay
  • 41
  • 9