Peek и Pop на UITableView не удается выполнить с помощью UISearchController

Peek и Pop работают с UISearchController. Однако Peek и Pop перестают работать после начала поиска в таблице с помощью updateSearchResults.

Я добавил Apple Поиск таблиц с демонстрацией UISearchController для поддержки Peek и Pop в качестве примера: введите описание изображения здесь

Проблема в том, что когда я начинаю искать таблицу, Peek и Pop больше не работают. Он просто выделяет подсветку: введите описание изображения здесь

Обновления, которые я сделал, были MainTableViewController:

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)
    }
}

Контроллер контекста поиска вмешивается в просмотр и поп (может быть, даже клавиатура)? Я могу заставить его работать, когда таблица изначально все данные, но не раз я начинаю использовать поиск. Я приложил рабочий образец здесь, если вы хотите запустить его и увидеть проблему.

Ответы

Ответ 1

Во-первых, в вашем MainTableViewController.viewDidLoad() вам также необходимо зарегистрировать свой resultsTableController.tableView, так как это отдельное представление, которое получит информацию peek/pop:

if traitCollection.forceTouchCapability == .available {
    previewingContext = registerForPreviewing(with: self, sourceView: tableView)
    if let resultVC = searchController.searchResultsController as? ResultsTableController {
        resultVC.registerForPreviewing(with: self, sourceView: resultVC.tableView)
    }
}

При тестировании этого решения я заметил странную проблему: первая строка в результирующем наборе не была подсмотренной, а пустые строки в результирующем наборе WERE peekable. Итак, второе исправление в previewingContext(_:viewControllerForLocation:):

func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
    guard let tableView = previewingContext.sourceView as? UITableView,
        let indexPath = tableView.indexPathForRow(at: location),

В исходном коде он использовал свойство tableView на MainTableViewController вместо tableView, которое было sourceView для взаимодействия.

Теперь это работает, когда вы ищете, а когда нет. Однако, когда вы вошли в поиск, но еще не указали какой-либо текст поиска, активен UISearchController, но UITableView является тем из MainTableViewController, и вы не можете дважды зарегистрируйте представление в виде источника. Итак, у нас есть еще немного работы:

// 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)
    }
}

В принципе, когда представлен UISearchController, мы отменим регистрацию MainTableViewController и зарегистрируем контроллер поиска. Когда он отклоняется, мы делаем обратное.

С этими изменениями, peek и pop работают во всех трех состояниях.