UITableView单元格上的Peek和Pop与UISearchController不兼容

16

Peek和Pop与UISearchController一起使用。但是,一旦使用updateSearchResults搜索表格,Peek和Pop就会停止工作。

我扩展了苹果的Table Search with UISearchController demo以支持Peek和Pop,以下是示例: enter image description here

问题在于当我开始搜索表格时,Peek和Pop不再起作用。它只是选择并突出显示它: enter image description here

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

搜索上下文控制器是否会干扰Peek和Pop(甚至可能是键盘)?当表格最初显示所有数据时,我可以使其正常工作,但一旦开始使用搜索功能,它就无法正常工作了。如果您想运行它并查看问题,请单击此处附加工作示例


你有什么问题? - Jitendra Modi
我更新了问题,并附上了截图和更多细节,谢谢 :) - TruMan1
我可以确认阻止 peek 和 pop 的不是键盘。我已经忽略了它,但问题仍然存在。 - TruMan1
抱歉,我没有3D Touch iPhone,在模拟器中也没有Xcode提供的设施。我想帮助你,但不幸的是我不能。非常抱歉。 - Jitendra Modi
1个回答

18

首先,在您的MainTableViewController.viewDidLoad()方法中,您需要注册您的resultsTableController.tableView,因为那是一个单独的视图,将接收到peek/pop信息:

首先,在您的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)
    }
}

在测试这个解决方案时,我注意到一个奇怪的问题,即结果集中的第一行无法预览,而结果集中的空白行可以预览。所以,在previewingContext(_: viewControllerForLocation:)中进行了第二个修复:

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

在原始代码中,它使用了MainTableViewController上的tableView属性,而不是作为交互的sourceViewtableView

现在,当您正在搜索时以及未搜索时,它都可以正常工作。但是,当您已经输入搜索但尚未输入任何搜索文本时,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在所有三种状态下都可以使用。


@TruMan1,我的回答有帮助吗? - Dave Weston
1
只要您有一个单独的searchResultsController,这个方法就可以正常工作。但是,如果您使用表视图控制器本身来显示搜索结果,则searchController.searchResultsController将为nil(根据苹果文档:“searchResultsController:显示搜索结果的视图控制器。如果要在显示可搜索内容的同一视图控制器中显示搜索结果,请指定nil。”)。 - vilmoskörte
1
{btsdaf} - dkrdennis
@dkrdennis提出的建议对我有用,但是我必须在调用持有搜索控制器的视图控制器上的registerForPreviewing(with:sourceView:)之后,在搜索控制器上调用它。 - simonbs
1
经过进一步测试,我想稍微修改一下我上面的评论。我发现当搜索控制器在UISearchControllerDelegate的willPresentSearchController(:)中注册预览时,它的效果最佳。同时,视图控制器应该被注销。相反,在willDismissSearchController(:)中则相反。 - simonbs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接