Search code examples
iosswiftuisearchcontrollerpeek-pop

3d Peek & Pop for search results


I use a Search Bar to filter my Table View. I display the search results in the same view controller that displays the searchable content. It works fine. Except one thing - 3d Peek and Pop is not working for the search results. I did tried the ‘Peek & Pop’ check box in Storyboard segue. I did tried programming peek & pop in my TableViewController. Result is the same: peek & pop works for table view cells but not for search result cells.

Here is the search and peek & pop code pieces:

    // Add a search bar
    searchController = UISearchController(searchResultsController: nil)
    tableView.tableHeaderView = searchController.searchBar
    searchController.searchResultsUpdater = self
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.dimsBackgroundDuringPresentation = false
    self.tableView.contentOffset = CGPoint(x: 0, y: searchController.searchBar.frame.height)

    // Register for preview
    if traitCollection.forceTouchCapability == .available {
        previewingContext = registerForPreviewing(with: self, sourceView: tableView)
    }


    func updateSearchResults(for searchController: UISearchController) {
        if let searchText = searchController.searchBar.text {
            filterContent(for: searchText)
            tableView.reloadData()
        }
    }

    // MARK: UIViewControllerPreviewingDelegate methods
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {        
        guard let tableView = previewingContext.sourceView as? UITableView,
            let indexPath = tableView.indexPathForRow(at: location),
            let cell = tableView.cellForRow(at: indexPath),
            let detailVC = storyboard?.instantiateViewController(withIdentifier: "AlarmViewController") as? AlarmViewController
        else { return nil }
        detailVC.alarm = alarms[indexPath.row]
        previewingContext.sourceRect = cell.frame       
        return detailVC
    }

    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        show(viewControllerToCommit, sender: self)
    }

Has anyone any ideas how to implement peek & pop for search results?

I guess the main problem is how to register for previewing the UISearchController?..


Solution

  • I made it work. There were couple of 'new kid on the block' mistakes. The correct code:

    // Add a search bar
    searchController = UISearchController(searchResultsController: nil)
    searchController.loadViewIfNeeded()
    tableView.tableHeaderView = searchController.searchBar
    searchController.searchResultsUpdater = self
    searchController.delegate = self
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.dimsBackgroundDuringPresentation = false
    self.tableView.contentOffset = CGPoint(x: 0, y: searchController.searchBar.frame.height)
    // Hide search bar on detailed view and preserve search results
        self.definesPresentationContext = true
    
    // Register for preview
    if traitCollection.forceTouchCapability == .available {
        previewingContext = registerForPreviewing(with: self, sourceView: tableView)
    }
    
    func updateSearchResults(for searchController: UISearchController) {
        if let searchText = searchController.searchBar.text {
            filterContent(for: searchText)
            tableView.reloadData()
        }
    }
    
    // MARK: UIViewControllerPreviewingDelegate methods
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {        
        guard let tableView = previewingContext.sourceView as? UITableView,
            let indexPath = tableView.indexPathForRow(at: location),
            let cell = tableView.cellForRow(at: indexPath),
            let detailVC = storyboard?.instantiateViewController(withIdentifier: "AlarmViewController") as? AlarmViewController
        else { return nil }
        detailVC.alarm = (searchController.isActive) ? searchResults[(indexPath.row)] : alarms[indexPath.row]
        previewingContext.sourceRect = cell.frame       
        return detailVC
    }
    
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        show(viewControllerToCommit, sender: self)
    }
    

    In short: 1) added delegating for searchController 2) using searchResults in UIViewControllerPreviewingDelegate if searchController.isActive

    Hope it helps someone.