Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make part of a string bold that matches a search string

I have a table of items and each item has a label. I also have a search bar that is used to filter the items in the table based on whether mySearchBar.text is a substring of myLabel.text.

That is all working fine, but I'd like to bold the portions of label text that match the search string.

The end product would be something similar to Google Maps search.

enter image description here

like image 922
Derek Soike Avatar asked Dec 18 '22 10:12

Derek Soike


2 Answers

Swift 4 : XCode 9.x

private func filterAndModifyTextAttributes(searchStringCharacters: String, completeStringWithAttributedText: String) -> NSMutableAttributedString {

    let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: completeStringWithAttributedText)
    let pattern = searchStringCharacters.lowercased()
    let range: NSRange = NSMakeRange(0, completeStringWithAttributedText.characters.count)
    var regex = NSRegularExpression()
    do {
        regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options())
        regex.enumerateMatches(in: completeStringWithAttributedText.lowercased(), options: NSRegularExpression.MatchingOptions(), range: range) {
            (textCheckingResult, matchingFlags, stop) in
            let subRange = textCheckingResult?.range
            let attributes : [NSAttributedStringKey : Any] = [.font : UIFont.boldSystemFont(ofSize: 17),.foregroundColor: UIColor.red ]
            attributedString.addAttributes(attributes, range: subRange!)
        }
    }catch{
        print(error.localizedDescription)
    }
    return attributedString
}

How to use :

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = UITableViewCell(style: .subtitle , reuseIdentifier: "Cell")
     cell.textLabel?.attributedText = self.filterAndModifyTextAttributes(searchStringCharacters: self.textFromSearchBar, completeStringWithAttributedText: searchResultString)
     return cell

}

RESULT

like image 175
Yash Bedi Avatar answered Jan 05 '23 20:01

Yash Bedi


Here's a sample of what I ended up implementing:

@IBOutlet weak var mySearchBar: UISearchBar!
@IBOutlet weak var myLabel: UILabel!

...

func makeMatchingPartBold(searchText: String) {

    // check label text & search text
    guard
        let labelText = myLabel.text,
        let searchText = mySearchBar.text
    else {
        return
    }

    // bold attribute
    let boldAttr = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: myLabel.font.pointSize)]

    // check if label text contains search text
    if let matchRange: Range = labelText.lowercased().range(of: searchText.lowercased()) {

        // get range start/length because NSMutableAttributedString.setAttributes() needs NSRange not Range<String.Index>
        let matchRangeStart: Int = labelText.distance(from: labelText.startIndex, to: matchRange.lowerBound)
        let matchRangeEnd: Int = labelText.distance(from: labelText.startIndex, to: matchRange.upperBound)
        let matchRangeLength: Int = matchRangeEnd - matchRangeStart

        // create mutable attributed string & bold matching part
        let newLabelText = NSMutableAttributedString(string: labelText)
        newLabelText.setAttributes(boldAttr, range: NSMakeRange(matchRangeStart, matchRangeLength))

        // set label attributed text
        myLabel.attributedText = newNameText
    }
}
like image 26
Derek Soike Avatar answered Jan 05 '23 21:01

Derek Soike