One of my controllers has an NSAttributeString which has a link in it:
@IBOutlet var textView: UITextView!
// Below is extracted from viewDidLoad()
let linkStr = "Click <a href='http://google.com'>here</a> for good times."
let attributedText = try! NSAttributedString(
data: linkStr.data(using: String.Encoding.unicode, allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
textView.attributedText = attributedText
I'm writing a unit test for the controller and I want to verify that the correct link was put on the "here" text. (The link is actually generated dynamically, which is why I want to test it).
Anyway, I can obviously get the unattributed text like this:
let text = viewController.textView.attributedText.string
// text == "Click here for good times."
I can also get the link attribute from "here" by doing something like this:
let url = uviewController.textView.attributedText.attribute(
"NSLink", at: 6, effectiveRange: nil)
// url == A URL object for http://google.com.
The problem is I had to hardcode that "6" for the at
parameter. The value of linkStr
could change in the future and I don't want to have to update my test every time. For this case, we can assume it will always have the word "here" with the link attached to that word.
So what I'd like to do is find the character for where the word "here" is in linkStr
and pass that value into the at
parameter in order to pull out the NSLink
attribute and verify it is pointing to the right URL. But I'm having trouble making heads or tails of how to use string ranges and indexes in Swift to pull this off.
Any suggestions?
Here's how you can do it without hardcoding. This is Swift 3 playground code based on your sample:
import UIKit
import PlaygroundSupport
let linkStr = "Click <a href='http://google.com'>here</a> for good times."
let attributedText = try! NSAttributedString(
data: linkStr.data(using: String.Encoding.unicode, allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
attributedText.enumerateAttribute(NSAttributedString.Key.link, in: NSMakeRange(0, attributedText.length), options: [.longestEffectiveRangeNotRequired]) { value, range, isStop in
if let value = value {
print("\(value) found at \(range.location)")
}
}
The print
statement outputs:
http://google.com/ found at 6
p.s. 'NSAttributedString.Key.link' is instead of 'NSLinkAttributeName' because of the renaming.
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