Highlight words in between response dynamic data names
"Work for Joy Bag is Started"
"Work for Jack & Jill is Ended"
"Work for Uncle Sam is Started"
Need to highlight "Joy Bag", "Jack & Sam" and "Uncle Same" with bold and rest in regular font.
class StudentCell: UITableViewCell
var welcomeData: StudentListModel.Data?{
didSet{
setCellData()
}
}
func setCellData() {
if let titleValue = welcomeData?.title{
let attributes = [[NSAttributedString.Key.foregroundColor:UIColor.red], [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17)]]
nameValue.attributedText = titleValue.highlightWordsIn(highlightedWords: "Work for is Started", attributes: attributes)
}
}
extension String {
func highlightWordsIn(highlightedWords: String, attributes: [[NSAttributedString.Key: Any]]) -> NSMutableAttributedString {
let range = (self as NSString).range(of: highlightedWords)
let result = NSMutableAttributedString(string: self)
for attribute in attributes {
result.addAttributes(attribute, range: range)
}
return result
}
}
From Given String "Work for Joy Bag is Started" In Between Work for - is Started or is Ended need to be Highlighted?
CodePudding user response:
The problem of your code is that your calling highlightWordsIn(highlightedWords:
with "Welcome to A B" which will never match the words you want to highlight. You need some code that will extract the substring you want to highlight, something like this using a regex (only works if the string is like on your examples):
if let titleValue = welcomeData?.title {
let substringToHighlight = titleValue.matches(regex: #"(?<=^Work for )\s* ([^,] ?)(?= is (Started|Ended)$)"#).first ?? ""
let attributes = [[NSAttributedString.Key.foregroundColor:UIColor.red], [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17)]]
nameValue.attributedText = titleValue.highlightWordsIn(highlightedWords: substringToHighlight, attributes: attributes)
}
Also added a method to the string extension:
extension String {
func matches(regex: String) -> [String] {
guard let regex = try? NSRegularExpression(pattern: regex, options: []) else { return [] }
let matches = regex.matches(in: self, options: [], range: NSMakeRange(0, self.count))
return matches.map { match in
return String(self[Range(match.range, in: self)!])
}
}
}
Another simpler regex to match between "for" and "is":
(?<=for )\s* ([^,] ?)(?= is)