12
votes

In iOS 9 I am using UISearchController and displaying its search bar within a UIViewController, I am experiencing a lot of lag the first time I click on the search bar and have tried everything i can think of to no avail...below is my code along with a link to a video of the lag happening - the lag happens on both the simulator and my device.

func setupUI() {
    self.view.backgroundColor = UIColor.whiteColor()

    // Required to properly display searchbar within nav & tabbar controllers
    self.extendedLayoutIncludesOpaqueBars = true // have tried setting this to false as well
    self.definesPresentationContext = true

    self.searchResultsController = AppDelegate.getViewController(ScheduleStoryboard.name, controllerName: ScheduleStoryboard.Identifiers.foodSearchResults) as? SearchResultsController

    self.searchController = UISearchController(searchResultsController: searchResultsController)
    self.searchController.searchResultsUpdater = self
    self.searchController.delegate = self
    self.searchController.dimsBackgroundDuringPresentation = true

    self.searchController.searchBar.delegate = self
    self.searchController.searchBar.placeholder = "Search foods..."
    self.searchController.searchBar.setBackgroundImage(UIImage(named: "background-searchbar")?.resizableImageWithCapInsets(UIEdgeInsetsMake(0, 0, 0, 0)), forBarPosition: .Any, barMetrics: .Default)
    self.searchController.searchBar.tintColor = UIColor.whiteColor()
    self.searchController.searchBar.sizeToFit()

    // this headerView does NOT belong to the tableView, its anchored on top of the tableView so that the searchbar remains fixed when scrolling
    self.headerView.addSubview(searchController.searchBar)

    self.tableView.delegate = self
    self.tableView.dataSource = self
    self.tableView.tableHeaderView?.backgroundColor = UIColor.clearColor()
    self.tableView.tableHeaderView?.addBorder(.Bottom, color: UIColor.groupTableViewBackgroundColor(), width: 0.25)

    self.segmentedControl.tintColor = UIColor.genioBlue()
}

Here is a link to the video showing whats happening: http://sendvid.com/xgq81stx

Thanks!

2
Have you been able to find a workaround for this? I'm facing the exact same issue - Nicolas Jakubowski
same issue for me as well. I haven't found a solution either. - Andrew J. Freyer
are you testing it on the simulator? or on your iPhone or iPad? The simulator is usually buggy so maybe connect an actual device to try it out. Hope that helps! Let me know if it does. - CoolPenguin
still the same issue? I'm having the exact same problem. After the first time, things go smooth. - SoundShock
I don't know what is the real cause of this bug, but in my case it because I added a UIRefreshControl to searchResultsController tableView. Remove it and no more slow animation. - kientux

2 Answers

0
votes

I've only ever created a search controller once, but I used a UITableViewController as my base class. Here is my implementation:

class SearchController: UITableViewController {
    let searchController = UISearchController(searchResultsController: nil)
    var items:[ArrayOfYourType]
    var filteredItems:[ArrayOfYourType]
    var scopeTitles:[String]?

override func viewDidLoad() {
    super.viewDidLoad()

    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar

    searchController.searchBar.scopeButtonTitles = scopeTitles
    searchController.searchBar.delegate = self
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if searchController.active {
        return filteredItems.count
    }
    return items.count
}

func filterContentForSearchText(searchText: String, scope: String = "All") {
    filteredItems = items.filter { item in
        //return true or false depending on your filter
        return true
    }
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.tableView.reloadData()
    })
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle,
        reuseIdentifier: nil)
    let item: String
    let category: String
    if searchController.active {
        item = filteredItems[indexPath.row].getTitle()
        category = filteredItems[indexPath.row].getCategory()
    }
    else {
        item = items[indexPath.row].getTitle()
        category = items[indexPath.row].getCategory()
    }
    cell.textLabel?.text = item
    cell.detailTextLabel?.text = category
    return cell
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    //your code here
}
}

//MARK: UISearchResultsUpdating
extension SearchController: UISearchResultsUpdating {
    func updateSearchResultsForSearchController(searchController: UISearchController) {
        if let _ = scopeTitles {
            let searchBar = searchController.searchBar
            let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
            filterContentForSearchText(searchController.searchBar.text!,scope:scope)
        }
        else {
            filterContentForSearchText(searchController.searchBar.text!)
        }
    }
}

//MARK: UISearchBarDelegate
extension SearchController: UISearchBarDelegate {
    func searchBar(searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
        filterContentForSearchText(searchBar.text!, scope: searchBar.scopeButtonTitles![selectedScope])
    }
}

I hope this helps :)

0
votes

Could it be possible that the image you are using for the background search bar is too large?

It might be quicker to create a gradient. Here is a good tutorial