Skip to content
AliSoftware edited this page Aug 20, 2016 · 5 revisions

How to detect when a link is tapped in a UILabel?

Best solution: prefer using a non-editable UITextView

If you really need to support links, I strongly suggest to use an UITextView (configured with its property editable=NO) instead of an UILabel. UITextView natively comes with support for URL links and have a dedicated delegate method for that (-textView:shouldInteractWithURL:inRange:). It's all built-in, so why bother?

Moreover, UITextView exposes its underlying NSLayoutManager and NSTextContainer so that we can use Apple's TextKit to compute the position of each character, which character is at the given coordinate (e.g. which character is drawn at that tapped CGPoint, etc) and more. By contrast UILabel does not expose its NSLayoutManager or NSTextContainer.

If you really need to stick with UILabel

OHAttributedStringAdditions introduced a new UILabel category in version 1.3.0 that allows you to compute (the best we could, using TextKit) the index of the character that lies under a given CGPoint.

That way it is now easy to detect the URL that lies under the tapped point of an UILabel:

  • Ensure the userInteractionEnabled property of your UILabel is set to YES
  • Add an UITapGestureRecognizer on your UILabel, and associate it with a selector / @IBAction (let's call it handleLabelTap:)
  • Implement that callback this way:
- (IBAction)handleLabelTap:(UITapGestureRecognizer *)tapGR
{
    // Only execute the rest of the code if the gesture ended (not during its intermediate states)
    if (tapGR.state == UIGestureRecognizerStateEnded)
    {
        CGPoint tapPoint = [tapGR locationInView:self.footerLabel];
        NSUInteger pos = [self.footerLabel characterIndexAtPoint:tapPoint];
        if (pos != NSNotFound)
        {
            NSURL* urlTapped = [self.footerLabel.attributedText URLAtIndex:pos effectiveRange:NULL];
            if (urlTapped) [[UIApplication sharedApplication] openURL:urlTapped];
        }
    }
}

For more info, see the AttributedStringDemo project provided in this GitHub repository. Similar code has been used to implement that in ASDViewController.m.