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.
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).
Alternatively, you can check for nil in
self.searchController.searchBar.selectedScopeButtonIndex
, return 0 innumberOfRowsInSection
if true, this will avoid the crash. When you callself.tableView.reloadData()
it will triggernumberOfRowsInSection
again, and this timeself.searchController.searchBar.selectedScopeButtonIndex
should be ready, not nil.