Swift 3: 在 NSAttributedString 中获取子字符串的属性
Swift 3: Getting attributes at substring in NSAttributedString
我的一个控制器有一个 NSAttributeString,其中有一个 link:
@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
我正在为控制器编写单元测试,我想验证 link 是否放在 "here" 文本中。 (link实际上是动态生成的,这就是我要测试它的原因)。
无论如何,我显然可以得到这样的无属性文本:
let text = viewController.textView.attributedText.string
// text == "Click here for good times."
我还可以从 "here" 中获取 link 属性,方法如下:
let url = uviewController.textView.attributedText.attribute(
"NSLink", at: 6, effectiveRange: nil)
// url == A URL object for http://google.com.
问题是我不得不为 at
参数硬编码“6”。 linkStr
的值将来可能会改变,我不想每次都更新我的测试。对于这种情况,我们可以假设它将始终包含单词 "here" 以及附加到该单词的 link。
所以我想做的是找到单词 "here" 在 linkStr
中的字符,并将该值传递给 at
参数以提取NSLink
属性并验证它指向正确的 URL。但是我无法确定如何使用 Swift 中的字符串范围和索引来实现这一点。
有什么建议吗?
以下是无需硬编码即可实现的方法。这是基于您的示例的 Swift 3 playground 代码:
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)")
}
}
print
语句输出:
http://google.com/ found at 6
p.s。由于重命名,'NSAttributedString.Key.link' 而不是 'NSLinkAttributeName'。
我的一个控制器有一个 NSAttributeString,其中有一个 link:
@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
我正在为控制器编写单元测试,我想验证 link 是否放在 "here" 文本中。 (link实际上是动态生成的,这就是我要测试它的原因)。
无论如何,我显然可以得到这样的无属性文本:
let text = viewController.textView.attributedText.string
// text == "Click here for good times."
我还可以从 "here" 中获取 link 属性,方法如下:
let url = uviewController.textView.attributedText.attribute(
"NSLink", at: 6, effectiveRange: nil)
// url == A URL object for http://google.com.
问题是我不得不为 at
参数硬编码“6”。 linkStr
的值将来可能会改变,我不想每次都更新我的测试。对于这种情况,我们可以假设它将始终包含单词 "here" 以及附加到该单词的 link。
所以我想做的是找到单词 "here" 在 linkStr
中的字符,并将该值传递给 at
参数以提取NSLink
属性并验证它指向正确的 URL。但是我无法确定如何使用 Swift 中的字符串范围和索引来实现这一点。
有什么建议吗?
以下是无需硬编码即可实现的方法。这是基于您的示例的 Swift 3 playground 代码:
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)")
}
}
print
语句输出:
http://google.com/ found at 6
p.s。由于重命名,'NSAttributedString.Key.link' 而不是 'NSLinkAttributeName'。