2

How to make the text as a hyperlink in NSTextView programmatically?

Like this:

Just click here to register

or like this:

Just http://example.com to register

I found this solution but it works only for iOS, not for macOS

  • 2
    Possible duplicate of [Simple clickable link in Cocoa and Swift](https://stackoverflow.com/questions/38340282/simple-clickable-link-in-cocoa-and-swift) – ielyamani Sep 15 '18 at 10:33
  • 1
    @Carpsen90 it is about NSTextField and it uses a storyboard, so it is not a programmatic way –  Sep 15 '18 at 10:36

3 Answers3

3

Try this:

let attributedString = NSMutableAttributedString(string: "Just click here to register")
let range = NSRange(location: 5, length: 10)
let url = URL(string: "https://www.apple.com")!

attributedString.setAttributes([.link: url], range: range)
textView.textStorage?.setAttributedString(attributedString)

// Define how links should look like within the text view
textView.linkTextAttributes = [
    .foregroundColor: NSColor.blue,
    .underlineStyle: NSUnderlineStyle.styleSingle.rawValue
]
Code Different
  • 90,614
  • 16
  • 144
  • 163
  • 2
    It works, thank you! Don't you also know how can I change the cursor to pointer when I hover the link? :) –  Sep 15 '18 at 15:22
  • 1
    The question was for MacOS not for iOS – StNickolay Jan 06 '21 at 10:51
  • 1
    Hi, on Swift 5 developing a macOS app, this does not produce a clickable link. Anything I'm missing to get it working? The text is blue an underlined properly but it's not clickable for some reason. – user3064009 Apr 18 '21 at 03:06
  • 1
    @user3064009 Check that your NSTextView is "Selectable" in Interface Builder. It's a checkbox and without it the NSTextView ignores mouse clicks, thus preventing your link from being clickable. – fsctl Jun 19 '22 at 10:47
1

If you needed set Font Size for links use this ->

    let input = "Your string with urls"
      
      let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
      let matches = detector.matches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count))
      
      let attributes = [NSAttributedString.Key.font: NSFont.systemFont(ofSize: 15)]
      let attributedString = NSMutableAttributedString(string: input, attributes: attributes)
      if matches.count > 0{
           for match in matches {
                guard let range = Range(match.range, in: input) else { continue }
                let url = input[range]
                
                attributedString.setAttributes([.link: url, .font: NSFont.systemFont(ofSize: 15)], range: match.range)
           
           
           }
      }
      
      youTextView.textStorage?.setAttributedString(attributedString)
neskafesha
  • 191
  • 5
0

Swift 5 / macOS 12 solution to make the link clickable and have the same font any NSTextField's you display in the same window:

Define some NSTextView IBOutlet (mine is called tutorialLink):

@IBOutlet weak var tutorialLink : NSTextView!

Then here's the styling code in one function:

fileprivate func initTutorialLink() {
    let attributedString = NSMutableAttributedString(string: "Here's a tutorial on how to set up a Digital Ocean S3 account.")
    
    // Set font for entire string
    let fontAttributes = [NSAttributedString.Key.font: NSFont.systemFont(ofSize: 13)]
    let range2 = NSRange(location: 0, length: 61)
    attributedString.setAttributes(fontAttributes, range: range2)
    
    // Set url and same font for just the link range
    let range = NSRange(location: 21, length: 40)
    let url = URL(string: tutorialUrl)!
    attributedString.setAttributes([.link: url, NSAttributedString.Key.font:NSFont.systemFont(ofSize: 13)], range: range)
    
    // Store the attributed string
    tutorialLink.textStorage?.setAttributedString(attributedString)
    
    // Mark how link text should be colored and underlined
    tutorialLink.linkTextAttributes = [
        .foregroundColor: NSColor.systemBlue,
        .underlineStyle: NSUnderlineStyle.single.rawValue
    ]
    
    // Give non-linked text same color as other labels
    tutorialLink.textColor = .labelColor
}

In IB, you obviously need to connect your NSTextView (called Scrollable Text View in the Objects Library) to the IBOutlet. Less obviously, you need to click the box to make the NSTextView Selectable. I don't know why exactly, but if it's not Selectable then your link will not react when clicked.

fsctl
  • 161
  • 8
  • 1
    > Non-selectable text views do not process any mouse events https://developer.apple.com/documentation/appkit/nstextview/1449297-selectable – benc Jun 17 '22 at 14:54