Here I had got attributed text from an api in which it is displayed on text view but later I got requirement that the attributed text needs search and when a word is searched it should display a highlight colour for matched words in the given html attributed text and for displaying attributed text I used text view I tried below code and here I didn't get any function to pass attributed string to search and tried below function worked but html tags showing in text view can any one help me how to resolve the issue ?
here is my code
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
}
}
Issue:
let attributedString = NSMutableAttributedString(string: targetString)
You are creating a NSAttributedString
with your HTML string without parsing. So you see the HTML tags.
You have already your own method that parse a HTML string into a NSAttributedString
, use it (and keep in mind we need a mutable one):
let attributedString = NSMutableAttributedString(attributedString: targetString.htmlAttributedString(fontSize: 14.0))
Now, the NSAttributedString
conversion removed the HTML tags (and interprets them if possible, because NSAttributedString
doesn't interprets ALL HTML tags, only a few ones). So the length, the ranges are all different.
So you can't do this anymore:
let range = NSRange(location: 0, length: targetString.utf16.count)
You need to update it to:
let range = NSRange(location: 0, length: attributedString.string.utf16.count)
Same here:
for match in regex.matches(in: targetString, options: .withTransparentBounds, range: range) {
To be updated to:
for match in regex.matches(in: attributedString.string, options: .withTransparentBounds, range: range) {