Swift iOS SearchController not Being Called in ViewDidLoad

337 views Asked by At

I have a search Controller who's view is being presented from another view controller. Basically I have a NavBarButton inside another view and when I press it the searchcontoller is displayed.

For some reason the search controller isn't being called in viewDidLoad. Any idea why?

Btw I didn't add the tableView methods because that's not where I'm having the problem. When I put a break point on var searchController: UISearchController! it hits it.

Inside viewDidLoad when I put a breakpoint on searchController(anything) it skips it so this is where the problem is.

Inside numberOfRowsInSection... When I put a break point on let scopeButtonIndex = self.searchController.searchBar.selectedScopeButtonIndex and when I press continue it crashes here because the selectedScopeButtonIndex returns a Nil value. I realized it's nil because it's not getting called in viewDidLoad self.searchController.searchBar.scopeButtonTitles = ["Sneaker Name","Sneaker Condition"]

Why is viewDidLoad not calling my searchController?

class SearchViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchResultsUpdating, UISearchBarDelegate, UISearchControllerDelegate {

@IBOutlet weak var tableView: UITableView!

var searchController: UISearchController!

var userContent = [Sneakers]()
var filteredSearchSneakerNames = [Sneakers]()
var filteredSearchSneakerConditions = [Sneakers]()

override func viewDidLoad() {
        super.viewDidLoad()

        let backgroundColor = UIView(frame: CGRectZero)
        self.tableView.tableFooterView = backgroundColor

        //Nothing below this comment inside viewDidLoad is being called 
        self.tableView.backgroundColor = UIColor.whiteColor()
        self.searchController = UISearchController(searchResultsController: nil)
        self.searchController.delegate = self
        self.searchController.searchBar.delegate = self
        self.searchController.searchResultsUpdater = self
        self.searchController.searchBar.showsCancelButton = true
        self.searchController.searchBar.placeholder = "Search..."
        self.searchController.searchBar.scopeButtonTitles = ["Sneaker Name","Sneaker Condition"]
        self.searchController.searchBar.returnKeyType = .Done
        self.navigationItem.hidesBackButton = true
        self.searchController.dimsBackgroundDuringPresentation = false
        self.navigationItem.titleView = searchController.searchBar
        self.searchController.hidesNavigationBarDuringPresentation = false
        self.definesPresentationContext = true
        self.searchController.searchBar.sizeToFit()
        self.tableView.tableHeaderView = self.searchController.searchBar
        self.tableView.reloadData()
    }

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    //I put a breakpoint here and it crashes
    let scopeButtonIndex = self.searchController.searchBar.selectedScopeButtonIndex

    if scopeButtonIndex == 0{
        return self.filteredSearchSneakerNames.count
    }else{
        return self.filteredSearchSneakerConditions.count
    }
}

func tableView(tableView: UITableView, cellForRowAtIndexPath...){
...
}

deinit{
        self.searchController = nil
    }

}

I didn't add in updateSearchResultsForSearchController or any of the other searchController methods because they aren't having any problems.

1

There are 1 answers

0
Leo Feng On BEST ANSWER

Try to move these two lines to the end of viewDidLoad. Your table view is coming from the storyboard as IBOutlet, meaning they are ready before viewDidLoad, calling the method tableFooterView on tableview triggers the method tableView:cellForRowAtIndexPath. Since your self.searchController is not setup at this point yet, you will get nil and crash. Moving these two lines at the end ensures that operation for table view starts after your data source is available (in this case, it's the searchController).

let backgroundColor = UIView(frame: CGRectZero)
self.tableView.tableFooterView = backgroundColor

Alternatively, you can check for nil in self.searchController.searchBar.selectedScopeButtonIndex, return 0 in numberOfRowsInSection if true, this will avoid the crash. When you call self.tableView.reloadData() it will trigger numberOfRowsInSection again, and this time self.searchController.searchBar.selectedScopeButtonIndex should be ready, not nil.