Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update search results when scope button changed. Swift UISearchController

How to update search results when scope button changed (after my click on scope)? Search results changed (with new scope) when I type again!

searchControl - config import UIKit

class ProductTableView: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchResultsUpdating
{

    @IBOutlet weak var tableView: UITableView!
    var searchController: UISearchController!

    var friendsArray = [FriendItem]()
    var filteredFriends = [FriendItem]()

    override func viewDidLoad()
    {
        super.viewDidLoad()

        searchController = UISearchController(searchResultsController: nil)
        searchController.searchBar.sizeToFit()
        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false
        searchController.searchBar.scopeButtonTitles = ["Title","SubTitle"]
        definesPresentationContext = true
        tableView.tableHeaderView = searchController.searchBar

        self.tableView.reloadData()


    }

Update Func When I type text NSLog print my text and scope number. When I change scope - nothing!!!

func updateSearchResultsForSearchController(searchController: UISearchController) {
    let searchText = searchController.searchBar.text
    let scope = searchController.searchBar.selectedScopeButtonIndex
    NSLog("searchText - \(searchText)")
    NSLog("scope - \(scope)")
    filterContents(searchText, scope: scope)
    tableView.reloadData()
}

Filter func

func filterContents(searchText: String, scope: Int)
    {

        self.filteredFriends = self.friendsArray.filter({( friend : FriendItem) -> Bool in
    var fieldToSearch: String?
            switch (scope){
            case (0):
                fieldToSearch = friend.title
            case(1):
                fieldToSearch = friend.subtitle
            default:
                fieldToSearch = nil
            }

            var stringMatch = fieldToSearch!.lowercaseString.rangeOfString(searchText.lowercaseString)
            return stringMatch != nil

        })
    }

Help me, please!

like image 271
aXXy Avatar asked Aug 11 '15 21:08

aXXy


1 Answers

The behaviour you're expecting is logical and seems on the surface to be correct, but actually isn't. Thankfully, there's an easy workaround.

Here's Apple's description of the method:

Called when the search bar becomes the first responder or when the user makes changes inside the search bar.

A scope change is a change in the search bar, right? Makes sense to me. But if you read the discussion, Apple makes it clear the behaviour isn't what you expect:

This method is automatically called whenever the search bar becomes the first responder or changes are made to the text in the search bar.

Not included in that: Changes to the scope. Weird thing to overlook, isn't it? Either the method should be called when the scope is changed, or the summary should be clear it isn't.

You can get the behaviour you want by adding the UISearchBarDelegate protocol to your view controller and setting searchController.searchBar.delegate to your view controller.

Then add this:

func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
    updateSearchResultsForSearchController(searchController)
}

This will cause updateSearchResultsForSearchController to be fired whenever the scope changes, as you're expecting. But instead, you might want to factor the meat of updateSearchResultsForSearchController into a new method that both updateSearchResultsForSearchController and selectedScopeButtonIndexDidChange call.

like image 101
Steven Fisher Avatar answered Sep 27 '22 18:09

Steven Fisher