I'm following an example from Apple to create a hyperlink in a NSTextField (via an attributed string), and though the hyperlink itself works, there is an issue with the cursor. Namely, when you hover over the hyperlink, it displays the normal I-beam cursor until you click it. After clicked once, it displays the proper pointing-hand cursor.
I've searched for a while and there doesn't seem to be an easy answer to this issue, which is confusing because hyperlinks seem as if they would be pretty common. People have suggested using hyperlinked NSButtons (how do you get underline on hover, then?) and NSTextViews previously, but that seems sort of hack-y. What's the proper way to do hyperlinks in OSX programming?
Note: I stumbled across this article which shows a way of doing this with textviews and "category". Is this the proper way to do things? I want to be writing maintainable and clean code.
Thank you!
Building on Apple's example and @stevesliva's answer, here's what I came up with:
import Cocoa
extension NSAttributedString {
/// Return an attributed string that looks like a hyperlink
///
/// Based on code at <https://developer.apple.com/library/mac/qa/qa1487/_index.html>
///
/// - parameters:
/// - string: text to be turned into a hyperlink
/// - URL: destination of the hyperlink
/// - returns: `NSAttributedString`
static func hyperlinkFromString(string: String, withURL URL: NSURL) -> NSAttributedString {
let attrString = NSMutableAttributedString(string: string)
let range = NSMakeRange(0, attrString.length)
attrString.beginEditing()
attrString.addAttribute(NSLinkAttributeName,
value: URL.absoluteString,
range: range)
attrString.addAttribute(NSForegroundColorAttributeName,
value: NSColor.blueColor(),
range: range)
attrString.addAttribute(NSUnderlineStyleAttributeName,
value: NSNumber(int: Int32(NSUnderlineStyle.StyleSingle.rawValue)),
range: range)
attrString.fixAttributesInRange(range)
attrString.endEditing()
return attrString
}
}
/// Subclass of NSTextField used to display hyperlinks
class HyperlinkTextField: NSTextField {
/// Set content to be a hyperlink
///
/// Based on code at <https://developer.apple.com/library/mac/qa/qa1487/_index.html>
///
/// - parameters:
/// - title: text displayed in field
/// - URL: destination of hyperlink
func setHyperlinkWithTitle(title: String, URL: NSURL) {
allowsEditingTextAttributes = true
selectable = true
attributedStringValue = NSAttributedString.hyperlinkFromString(title,
withURL: URL)
}
/// Always display a pointing-hand cursor
override func resetCursorRects() {
addCursorRect(bounds, cursor: NSCursor.pointingHandCursor())
}
}
Good question! Hyperlinks in OSX controls, while functional, seem a little clunky.
I believe it's because the NSTextField doesn't have the focus until the first click.
The likely solution is to use this related question's answer(s). I was going to copy and paste some code, but the dscussion there is useful. The bottommost answer about how to subclass the view is likely the most robust.
The NSCursor class methods contain a list of the other possible cursor types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With