Peek and Pop is working with a UISearchController
. However, Peek and Pop stops working once you start searching the table using updateSearchResults
.
I've extended Apple's Table Search with UISearchController demo to support Peek and Pop as an example:
Problem is when I start searching the table, Peek and Pop doesn't work anymore. It just select highlights it:
The updates I made were to MainTableViewController
are:
class MainTableViewController: BaseTableViewController, UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating {
override func viewDidLoad() {
super.viewDidLoad()
...
if traitCollection.forceTouchCapability == .available {
registerForPreviewing(with: self, sourceView: tableView)
}
}
}
extension MainTableViewController: UIViewControllerPreviewingDelegate {
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = tableView?.indexPathForRow(at: location),
let cell = tableView?.cellForRow(at: indexPath),
let controller = storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController
else { return nil }
previewingContext.sourceRect = cell.frame
controller.product = products[0]
return controller
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
guard let controller = viewControllerToCommit as? DetailViewController else { return }
controller.product = products[0]
show(controller, sender: self)
}
}
Is the search context controller interfering with peek and pop (could even be the keyboard)? I can get it to work when the table initially all data, but it does not once I start using the search. I attached a working sample here if you want to run it and see the issue.
This is a simple tutorial on how to use the new UISearchController to add search capability to your UITableViews. The UISearchController was introduced a couple years ago in iOS 8 to replace the now deprecated UISearchDisplayController. In the new search controller, it is easier to add search to your table views.
The following is pretty basic UITableView stuff. One function indicates how many sections we have, another indicates how many rows we have, and the final override configures the cell with data. They all use the data source unfilteredNFLTeams which is an array that I populate in the viewDidLoad function.
In Interface Builder, add a UITableViewController to your storyboard. By default, the UITableViewController will use dynamic cells. That is perfect for our demo. The only other configuration we need to do is to configure our dynamic cell. Click on the cell and give it a reuse identifier. I labeled mine “basicCell.”
The UISearchController was introduced a couple years ago in iOS 8 to replace the now deprecated UISearchDisplayController. In the new search controller, it is easier to add search to your table views.
First, in your MainTableViewController.viewDidLoad()
you need to also register your resultsTableController.tableView
, since that is a separate view that will receive peek/pop information:
if traitCollection.forceTouchCapability == .available {
previewingContext = registerForPreviewing(with: self, sourceView: tableView)
if let resultVC = searchController.searchResultsController as? ResultsTableController {
resultVC.registerForPreviewing(with: self, sourceView: resultVC.tableView)
}
}
When testing this solution, I noticed a strange problem, that the first row in the result set wasn't peekable, and blank rows in the result set WERE peekable. So, the second fix in previewingContext(_:viewControllerForLocation:)
:
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let tableView = previewingContext.sourceView as? UITableView,
let indexPath = tableView.indexPathForRow(at: location),
In your original code, it was using the tableView
property on the MainTableViewController
instead of the tableView
that was the sourceView
for the interaction.
Now, this works when you're searching, and when you're not. However, when you've entered the search, but haven't entered any search text yet, the UISearchController
is active, but the UITableView
is the one from MainTableViewController
, and you cannot register a view as a source view twice. So, we have a little more work to do:
// local property to store the result from registerForPreviewing(with:sourceView:)
var previewingContext: UIViewControllerPreviewing?
func didPresentSearchController(_ searchController: UISearchController) {
if let context = previewingContext {
unregisterForPreviewing(withContext: context)
previewingContext = searchController.registerForPreviewing(with: self, sourceView: tableView)
}
}
func didDismissSearchController(_ searchController: UISearchController) {
if let context = previewingContext {
searchController.unregisterForPreviewing(withContext: context)
previewingContext = registerForPreviewing(with: self, sourceView: tableView)
}
}
Basically, when the UISearchController
is presented, we unregister MainTableViewController
and register the search controller. When it is dismissed, we do the reverse.
With these changes, peek and pop work in all three states.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With