Search code examples
iosuiviewtouch

UITextView should detect links, but otherwise, should propagate touch to view below


I have a text view, where I want to detect links, but when there isn't a link at the touch point, it should propagate the touch to view below (it currently doesn't). It will be contained in a table view cell, and if the user taps a link, it should interact (it works), but when another point is tapped, it should select the table view cell.

I needed text to be unselectable, so I've followed https://stackoverflow.com/a/27264999/811405 and implemented:

-(BOOL)canBecomeFirstResponder{
    return NO;
}

It wasn't sending the touch events below before that too, but I've included it just is case it interferes with a solution.


Solution

  • Instead of preventing your text view from becoming first responder, you need to subclass the hitTest method so that it returns the textView when the click occured inside a link and return nil otherwise.

    @interface LinkOnlyTextView : UITextView
    @end
    
    @implementation LinkOnlyTextView
    
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
        NSUInteger glyphIndex = [self.layoutManager glyphIndexForPoint:point inTextContainer:self.textContainer fractionOfDistanceThroughGlyph:nullptr];
        NSUInteger characterIndex = [self.layoutManager characterIndexForGlyphAtIndex:glyphIndex];
        if (characterIndex < self.textStorage.length) {
            if ([self.textStorage attribute:NSLinkAttributeName atIndex:characterIndex effectiveRange:nullptr]) {
                return self;
            }
        }
        return nil;
    }
    
    @end
    

    There is a Swift version of this code snippet provided by @blwinters in a later answer to this question here: https://stackoverflow.com/a/47913329/1279096