NSAttributedString
clickable link
iOS development
Swift programming
hyperlink creation

How can I make a clickable link in an NSAttributedString?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

An NSAttributedString can store link metadata, but the string alone does not become interactive just because it contains a .link attribute. To make a link actually tappable on iOS, you need both the attributed string and a view that knows how to interpret link attributes, most commonly UITextView.

That is the part many people miss. NSAttributedString describes the content, but the hosting view decides whether the user can interact with it.

The first step is to mark the desired range with a link:

swift
1import UIKit
2
3let text = NSMutableAttributedString(
4    string: "Read the documentation on Apple Developer."
5)
6
7let range = (text.string as NSString).range(of: "Apple Developer")
8text.addAttributes([
9    .link: URL(string: "https://developer.apple.com")!,
10    .foregroundColor: UIColor.systemBlue,
11    .underlineStyle: NSUnderlineStyle.single.rawValue
12], range: range)

At this point, the attributed string contains link information, but it is still only data. Nothing is clickable yet until a supporting view renders it.

UILabel can display attributed text, but it does not natively handle clickable links. UITextView does:

swift
1import UIKit
2
3final class LinkViewController: UIViewController {
4    private let textView = UITextView()
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8
9        textView.isEditable = false
10        textView.isScrollEnabled = false
11        textView.backgroundColor = .clear
12        textView.attributedText = makeText()
13
14        view.addSubview(textView)
15        textView.frame = view.bounds.insetBy(dx: 20, dy: 40)
16    }
17
18    private func makeText() -> NSAttributedString {
19        let text = NSMutableAttributedString(
20            string: "Read the documentation on Apple Developer."
21        )
22
23        let range = (text.string as NSString).range(of: "Apple Developer")
24        text.addAttributes([
25            .link: URL(string: "https://developer.apple.com")!,
26            .foregroundColor: UIColor.systemBlue,
27            .underlineStyle: NSUnderlineStyle.single.rawValue
28        ], range: range)
29
30        return text
31    }
32}

With this setup, the linked text is interactive without needing your own tap-location hit testing.

If you want to open some links internally or prevent automatic navigation, use the text view delegate:

swift
1import UIKit
2
3final class LinkDelegateExample: NSObject, UITextViewDelegate {
4    func textView(
5        _ textView: UITextView,
6        shouldInteractWith url: URL,
7        in characterRange: NSRange,
8        interaction: UITextItemInteraction
9    ) -> Bool {
10        if url.scheme == "myapp" {
11            print("Handle internal route:", url.absoluteString)
12            return false
13        }
14
15        return true
16    }
17}

This lets you treat some links as external URLs and others as app-specific routes.

What If You Must Use UILabel?

If the design requires UILabel, clickable links become a manual problem. You need to:

  1. display the attributed text
  2. attach a gesture recognizer
  3. map the tap location to a character range
  4. inspect whether that range has a .link attribute

That is possible, but it is more code and easier to get wrong. If the main requirement is interactive rich text, UITextView is usually the simpler and more accessible control.

If you want one consistent link appearance across the whole text view, set linkTextAttributes:

swift
1textView.linkTextAttributes = [
2    .foregroundColor: UIColor.systemRed,
3    .underlineStyle: NSUnderlineStyle.single.rawValue
4]

That is often cleaner than repeating the same color and underline attributes in every linked range.

Common Pitfalls

The biggest mistake is adding a .link attribute and then displaying the attributed string in UILabel, expecting the link to become tappable automatically. It will not.

Another common issue is forgetting to set isEditable = false on UITextView, which makes the control behave like an editor instead of a simple read-only text surface.

Developers also sometimes style text to look like a link without actually adding the .link attribute. Blue underlined text is not interactive unless the attribute and the hosting view both support it.

Finally, if you implement custom label hit testing, be careful about accessibility. UITextView already handles many details that custom gesture logic has to recreate manually.

Summary

  • A clickable link needs both a .link attribute and a view that understands link interaction.
  • 'UITextView is the simplest UIKit control for tappable attributed links.'
  • Use the text view delegate when you need to intercept or customize link taps.
  • 'UILabel can show linked styling, but clickable behavior there is manual work.'
  • Keep styling and interaction separate: appearance alone does not make a link interactive.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.