TTTAttributedLabel links not clickable after adding a UITapGestureRcognizer on the label

302 views Asked by At

I have a TTTAttributedLabel to detect the URLs contained in my label, and now I also want to detect @menions. To do so, I've added a UITapGestureRecognizer to the label and on each tap I'm checking if the tapped word starts with @, etc.

My custom logic works properly, but now the URL detection of the TTTAttributedLabel is broken. I've tried setting the delegate to my UITapGestureRecognizer and overriding

override func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

but the URL clicks are still not being detected. Any idea of how I can have both functionalities on my label?

EDIT, Some of my code:

The UITapGestureRcognizer is initialized as such:

commentLabel.isUserInteractionEnabled = true;
let labelTap = UITapGestureRecognizer(target: self, action: #selector(labelTapped(_:)))
labelTap.delegate = self
commentLabel.addGestureRecognizer(labelTap)

My tap function is the following:

@objc func labelTapped(_ sender: UITapGestureRecognizer) {
        // Find the character that was tapped...
        let textLabel = sender.view as? UILabel
        let tapLocation = sender.location(in: textLabel)

        // init text storage
        var textStorage: NSTextStorage? = nil
        if let attributedText = textLabel?.attributedText {
            textStorage = NSTextStorage(attributedString: attributedText)
        }
        let layoutManager = NSLayoutManager()
        textStorage?.addLayoutManager(layoutManager)

        // init text container
        let textContainer = NSTextContainer(size: CGSize(width: textLabel?.frame.size.width ?? 0.0, height: (textLabel?.frame.size.height ?? 0.0) + 100))
        textContainer.lineFragmentPadding = 0
        textContainer.maximumNumberOfLines = textLabel?.numberOfLines ?? 0
        if let lineBreakMode = textLabel?.lineBreakMode {
            textContainer.lineBreakMode = lineBreakMode
        }

        layoutManager.addTextContainer(textContainer)

        // Get the character that was tapped
        let characterIndex = layoutManager.characterIndex(
            for: tapLocation,
            in: textContainer,
            fractionOfDistanceBetweenInsertionPoints: nil)

        // Now find the word that was tapped
        let word = textLabel?.text?.getWordFromCharacteratIndex(characterIndex) // Another custom function I've built that returns the word form a character

        // And match it with a mentioned user
        // Some code to match the word with my mentions pattern
        // ...........
    }
2

There are 2 answers

1
Ved Sharma On

You can try the other label where you can detect #hashtags, @usernames & hyperlinkes

https://github.com/optonaut/ActiveLabel.swift

0
Lucas P. On

I figured it out. The UITapGestureRecognizer was cancelling the tap event after it was recognized, so by setting labelTap.cancelsTouchesInView = false to my UITapGestureRegognizer, the touch even gets delivered to both callbacks. And I don't even need to implement the shouldRecognizeSimultaneouslyWith otherGestureRecognizer delgate method, as the TTTAttributedLabel is using touch events instead of UITapGestureRecognizer` for its URL detection.