[ios] Create tap-able "links" in the NSAttributedString of a UILabel?

Most simple and reliable approach is to use UITexView as Kedar Paranjape recommended. Based on answer of Karl Nosworthy I finally came up with a simple UITextView subclass:

class LinkTextView: UITextView, UITextViewDelegate {

typealias Links = [String: String]

typealias OnLinkTap = (URL) -> Bool

var onLinkTap: OnLinkTap?

override init(frame: CGRect, textContainer: NSTextContainer?) {
    super.init(frame: frame, textContainer: textContainer)
    isEditable = false
    isSelectable = true
    isScrollEnabled = false //to have own size and behave like a label   
    delegate = self
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
}

func addLinks(_ links: Links) {
    guard attributedText.length > 0  else {
        return
    }
    let mText = NSMutableAttributedString(attributedString: attributedText)
    
    for (linkText, urlString) in links {
        if linkText.count > 0 {
            let linkRange = mText.mutableString.range(of: linkText)
            mText.addAttribute(.link, value: urlString, range: linkRange)
        }
    }
    attributedText = mText
}

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
    return onLinkTap?(URL) ?? true
}

// to disable text selection
func textViewDidChangeSelection(_ textView: UITextView) {
    textView.selectedTextRange = nil
}

}

Usage is very simple:

    let linkTextView = LinkTextView()
    let tu = "Terms of Use"
    let pp = "Privacy Policy"
    linkTextView.text = "Please read the Some Company \(tu) and \(pp)"
    linkTextView.addLinks([
        tu: "https://some.com/tu",
        pp: "https://some.com/pp"
    ])
    linkTextView.onLinkTap = { url in
        print("url: \(url)")
        return true
    }

Note that isScrollEnabled is false by default, as in most cases we need small label-like view with own size and without scrolling. Just set it true if you want a scrollable text view.

Also note that UITextView unlike UILabel has default text padding. To remove it and make layout same as in UILabel just add: linkTextView.textContainerInset = .zero

Implementing onLinkTap closure is not necessary, without it URLs is automatically open by UIApplication.

As Text selection is undesirable in most cases, but it can't be turned off it is dismissed in delegate method (Thanks to Carson Vo)

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64 Wrapping a react-router Link in an html button How to make a hyperlink in telegram without using bots? React onClick and preventDefault() link refresh/redirect? How to put a link on a button with bootstrap? How link to any local file with markdown syntax? link with target="_blank" does not open in new tab in Chrome How to create a link to another PHP page How to determine the current language of a wordpress page when using polylang? How to change link color (Bootstrap) How can I make a clickable link in an NSAttributedString?

Examples related to uilabel

How to make a UILabel clickable? Figure out size of UILabel based on String in Swift How to underline a UILabel in swift? Adding space/padding to a UILabel How to set textColor of UILabel in Swift Adjust UILabel height to text Setting UILabel text to bold How do I make an attributed string using Swift? How do I change the font size of a UILabel in Swift? how do I change text in a label with swift?

Examples related to nsattributedstring

Swift: Display HTML data in a label or textView How to underline a UILabel in swift? How do I make an attributed string using Swift? How can I make a clickable link in an NSAttributedString? Change string color with NSAttributedString? boundingRectWithSize for NSAttributedString returning wrong size NSAttributedString add text alignment Convert HTML to NSAttributedString in iOS Bold & Non-Bold Text In A Single UILabel? How do you use NSAttributedString?

Examples related to uitapgesturerecognizer

How to make a UILabel clickable? tap gesture recognizer - which object was tapped? UITapGestureRecognizer - single tap and double tap Create tap-able "links" in the NSAttributedString of a UILabel?