Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Highlighting search result in UITableView cell iOS Swift

I have implemented a search bar in a TableView. Now I want to highlight the result. For example, if I have typed two letters then those two letters should be highlighted in the resultant TableView that drops down from the search bar. Can anyone help me to do this? I know I should use custom cells for this, but am lost implementing it.

like image 749
Ganesh Kumar Avatar asked Nov 05 '15 11:11

Ganesh Kumar


4 Answers

Here is the second way to attribute text in tableview

   let initialtext =   "Hello World"
    let attrString: NSMutableAttributedString = NSMutableAttributedString(string: initialtext)

let range: NSRange = (initialtext as NSString).rangeOfString(("World" , options:NSStringCompareOptions.CaseInsensitiveSearch])


    attrString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)


    cell!.textLabel?.attributedText = attrString
like image 122
Vijayvir Sing Pantlia Avatar answered Oct 21 '22 19:10

Vijayvir Sing Pantlia


@Vijay has a good, correct answer for this post.

I modified this slightly for my own purposes (bolding the text in my search results) by creating a function that accepts the searchString and the string you want to modify - the resultString - and returns an attributedString that can be applied to a UILabel.

I also had this check for the lowercaseString attribute, so that regardless of what I typed into my search bar, my string would match the characters rather than the case (this requirement may be different, depending on your use-case).

func boldSearchResult(searchString: String, resultString: String) -> NSMutableAttributedString {

    let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: resultString)
    let pattern = searchString.lowercaseString
    let range: NSRange = NSMakeRange(0, resultString.characters.count)

    let regex = try! NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions())

    regex.enumerateMatchesInString(resultString.lowercaseString, options: NSMatchingOptions(), range: range) { (textCheckingResult, matchingFlags, stop) -> Void in
        let subRange = textCheckingResult?.range
        attributedString.addAttribute(NSFontAttributeName, value: UIFont.customBoldedFontNameWithSize(15.0), range: subRange!)
    }

    return attributedString

}

Note: I had a custom bolded font to work with, but you could always use UIFont.boldSystemFontOfSize(fontSize: CGFloat) or something like that to get a similar effect.

Then, just add the result to your label by doing (some variation of):

cell.myCustomLabel.attributedText = boldSearchResult(mySearchText, resultString: textForBolding)
like image 28
BAP Avatar answered Oct 21 '22 20:10

BAP


Swift 5 version of Vijayvir's answer:

let initialtext = "Hello, World!"

let attrString: NSMutableAttributedString = NSMutableAttributedString(string: initialtext)

let range = (initialtext as NSString).range(of: "World", options: .caseInsensitive)

attrString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red, range: range)

cell.textLabel?.attributedText = attrString

Update 2020: Here's a simple String extension you can use to easily make an attributed string.

extension String {

    func highlightText(
        _ text: String,
        with color: UIColor,
        caseInsensitivie: Bool = false,
        font: UIFont = .preferredFont(forTextStyle: .body)) -> NSAttributedString
    {
        let attrString = NSMutableAttributedString(string: self)
        let range = (self as NSString).range(of: text, options: caseInsensitivie ? .caseInsensitive : [])
        attrString.addAttribute(
            .foregroundColor,
            value: color,
            range: range)
        attrString.addAttribute(
            .font,
            value: font,
            range: NSRange(location: 0, length: attrString.length))
        return attrString
    }

}
like image 8
henrik-dmg Avatar answered Oct 21 '22 20:10

henrik-dmg


You could achieve this by find the search term string range from your result string and adding attributed string at that range. Find the sample code below,

Objective-C

NSString *searchTerm = /* SEARCH_TERM */;
NSString *resultText = /* YOUR_RESULT_TEXT */;

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:resultText];

NSString *pattern = [NSString stringWithFormat:@"(%@)", searchTerm];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:kNilOptions error:nil];
NSRange range = NSMakeRange(0, resultText.length);

[regex enumerateMatchesInString:resultText options:kNilOptions range:range usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {

    NSRange subStringRange = [result rangeAtIndex:1];

    [attributedString addAttribute:NSForegroundColorAttributeName
                             value:[UIColor redColor]
                             range:subStringRange];
}];

Swift (TESTED)

let searchTerm = "" /* SEARCH_TERM */
let resultText = "" /* YOUR_RESULT_TEXT */
let attributedString:NSMutableAttributedString = NSMutableAttributedString(string: resultText)
let pattern = "(\(searchTerm))"
let range:NSRange = NSMakeRange(0, resultText.characters.count)

let regex = try! NSRegularExpression( pattern: pattern, options: NSRegularExpressionOptions())
regex.enumerateMatchesInString(
     resultText,
     options: NSMatchingOptions(),
     range: range,
     usingBlock: {
        (textCheckingResult, matchingFlags, stop) -> Void in
           let subRange = textCheckingResult?.range
            attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: subRange!)
            }
        )
like image 5
Vijay Avatar answered Oct 21 '22 19:10

Vijay