如何在 swift 3 中的属性文本中搜索单词?

How to search word in a attributed text in swift 3?

在这里,我从 api 中获得了属性文本,它显示在文本视图中,但后来我得到了需要搜索属性文本的要求,并且当搜索一个词时,它应该显示高亮颜色在给定的 html 属性文本中匹配单词并显示属性文本] 标签显示在文本视图中,谁能帮我解决这个问题?

这是我的代码

 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchText != "" {
            let attributedString = generateAttributedString(with: searchText, targetString: (self.FAQModel?.content)!)
            self.FAQTextView.attributedText = attributedString
        }
        else {
            let attributedString = self.FAQModel?.content.htmlAttributedString(fontSize: 14.0)
            self.FAQTextView.attributedText = attributedString
        }
    }

    func generateAttributedString(with searchTerm: String, targetString: String) -> NSAttributedString? {
        let attributedString = NSMutableAttributedString(string: targetString)
        do {
            let regex = try NSRegularExpression(pattern: searchTerm, options: .caseInsensitive)
            let range = NSRange(location: 0, length: targetString.utf16.count)
            for match in regex.matches(in: targetString, options: .withTransparentBounds, range: range) {
                attributedString.addAttribute(NSAttributedStringKey.font, value: UIFont.systemFont(ofSize: 14), range: match.range)
                attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.red, range: match.range)
            }
            return attributedString
        } catch _ {
            NSLog("Error creating regular expresion")
            return nil
        }
    } 

问题:

let attributedString = NSMutableAttributedString(string: targetString)

您正在使用 HTML 字符串创建一个 NSAttributedString 而不进行解析。所以你看到了 HTML 标签。

您已经有了自己的方法,可以将 HTML 字符串解析为 NSAttributedString,使用它(请记住我们需要一个可变的):

let attributedString = NSMutableAttributedString(attributedString: targetString.htmlAttributedString(fontSize: 14.0))

现在,NSAttributedString 转换删除了 HTML 标签(并尽可能解释它们,因为 NSAttributedString 不解释所有 HTML 标签,只有少数那些)。所以长度,范围都是不同的。

所以你不能再这样做了:

let range = NSRange(location: 0, length: targetString.utf16.count)

您需要将其更新为:

let range = NSRange(location: 0, length: attributedString.string.utf16.count)

这里也一样:

for match in regex.matches(in: targetString, options: .withTransparentBounds, range: range) {

待更新为:

for match in regex.matches(in: attributedString.string, options: .withTransparentBounds, range: range) {