Search code examples
iosswiftuilabelnsattributedstring

NSAttributedString click event in UILabel using Swift


Suppose I have an AttributedString: "Already have an account? Sign in!".

I am placing this String in UILabel. Now when a user clicks on "Sign in!", the current viewController should go to another viewController or some function should be called while clicking on sign in.

Any code or suggestion should be fine.


Solution

  • There's no need to use a separate gesture recognizer as some of the answers state. Instead, you can use attributed text in combination with the UITextViewDelegate's textView:shouldInteractWithURL:inRange:interaction: method to achieve this, ex:

    class ViewController: UIViewController, UITextViewDelegate {
        
        @IBOutlet weak var textView: UITextView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let text = NSMutableAttributedString(string: "Already have an account? ")
            text.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 12), range: NSMakeRange(0, text.length))
            
            let selectablePart = NSMutableAttributedString(string: "Sign in!")
            selectablePart.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 12), range: NSMakeRange(0, selectablePart.length))
            // Add an underline to indicate this portion of text is selectable (optional)
            selectablePart.addAttribute(NSAttributedString.Key.underlineStyle, value: 1, range: NSMakeRange(0,selectablePart.length))
            selectablePart.addAttribute(NSAttributedString.Key.underlineColor, value: UIColor.black, range: NSMakeRange(0, selectablePart.length))
            // Add an NSLinkAttributeName with a value of an url or anything else
            selectablePart.addAttribute(NSAttributedString.Key.link, value: "signin", range: NSMakeRange(0,selectablePart.length))
            
            // Combine the non-selectable string with the selectable string
            text.append(selectablePart)
            
            // Center the text (optional)
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.alignment = NSTextAlignment.center
            text.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, text.length))
            
            // To set the link text color (optional)
            textView.linkTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.black, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12)]
            // Set the text view to contain the attributed text
            textView.attributedText = text
            // Disable editing, but enable selectable so that the link can be selected
            textView.isEditable = false
            textView.isSelectable = true
            // Set the delegate in order to use textView(_:shouldInteractWithURL:inRange)
            textView.delegate = self
        }
        
        func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
    
            // **Perform sign in action here**
            
            return false
        }
    }