UIApplication 的“beginIgnoringInteractionEvents”不工作

UIApplication's `beginIgnoringInteractionEvents` not working

首先,对于长问题,我深表歉意,我个人更喜欢简短而准确的问题。

背景

我正在 UITableView 中开发搜索功能。为了存储数据,我正在使用 core data。为了显示我使用 NSFetchedResultsController 的结果。在我的视图模型中,我有一个单独的 NSFetchedResultsController 来表示搜索结果。

目前我正在使用以下方法

`textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String)` 

UITextFieldDelegate 听取我 UITextField 中的变化并基于此我开始搜索。

我的 perform fetch 部分看起来像这样

//
// ALL of this operation Run on MainQueue
//
// Preparing NSFetchRequest and setting 
// it's predicate Goes here 
// 

UIApplication.shared.beginIgnoringInteractionEvents()

managedObjectContext?.perform {
        do {
            try self.allContactSearchFetchResultController?.performFetch()
            DispatchQueue.main.async {
                UIApplication.shared.endIgnoringInteractionEvents()
                // calling the delegate which will reload the UITableView
            }

        } catch {
            print("Error occur")
            // TODO 
            // handle error here
        }
    }

我已停止用户交互,以便用户在搜索结束前无法再通过键盘输入。如果启动多个搜索,tableview 将无限期地重新加载,并且应用程序在访问以下

时崩溃
managedObject = allContactSearchFetchResultController?.object(at: indexPath)

来自 UITableViewDataSource

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

为了运行一次一个搜索操作,我已经开始忽略用户交互。搜索结束后我结束忽略用户交互。

问题

它工作正常,直到我注意到按住退格键,开始忽略用户交互不起作用。

所以问题出现了,我如何检查开始忽略用户交互是否正常工作。我放了两个断点

一个在

UIApplication.shared.beginIgnoringInteractionEvents()

另一个在

UIApplication.shared.endIgnoringInteractionEvents()

当我按住退格键时,多个断点命中了 beginIgnoringInteractionEvents 而没有命中 endIgnoringInteractionEvents

可能的解决方案:

我已经找到了使用 managedObjectContext?.performAndWait 而不是 managedObjectContext?.perform 的方法。但这卡住了主线程。我必须在 UILabel 中显示当前状态为 searching...。如果我使用 managedObjectContext?.performAndWait 它会省略阶段搜索并在一段时间后直接显示搜索结果。相反,我更喜欢忽略用户交互并显示搜索操作的当前状态。

如有任何帮助,我们将不胜感激。 T.I.A

因为我想停下来

tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)

我正在准备搜索结果。结果取自 allContactSearchFetchResultController,但我将其分配给新的 NSFetchedResultsController,但 UITableView 根据 [=14] 中的旧节数和行数调用 managedObject =]如下

allContactSearchFetchResultController?.sections?.count

allContactSearchFetchResultController?.sections[section].numberOfObject // There are more guard involved in this number of row fetching, for simplicity purpose i omitted those.

但是当我将 allContactSearchFetchResultController 分配给一个新的 NSFetchedResultsController 时,table 视图继续从 cellForRowAt 请求位于 IndexPath 的旧托管对象,因为 table 视图不知道我已将它分配给新的 NSFetchedResultsController。所以在这种情况下,我的解决方案是创建一个新的本地 NSFetchedResultsController 准备它,在 managedObjectContext 的队列上对其执行提取。当结果准备就绪时,切换到 mainQueue 并分配它。我的执行提取部分现在看起来像这样。

//
// ALL of this operation Run on MainQueue
//
let allFetchRequest = prepareCommonFetchRequest()
    allFetchRequest.predicate = NSPredicate.init(format: "name CONTAINS[cd] %@ || mobile_number CONTAINS[cd] %@", searchString, searchString)

    let tempAllContactSearchFetchResultController = NSFetchedResultsController.init(fetchRequest: allFetchRequest,
                                                                            managedObjectContext: managedObjectContext!,
                                                                            sectionNameKeyPath: "section_key",
                                                                            cacheName: nil)

managedObjectContext?.perform {
    do {
        try self.allContactSearchFetchResultController?.performFetch()
        DispatchQueue.main.async {
            self.allContactSearchFetchResultController = tempAllContactSearchFetchResultController
            // calling the delegate which will reload the UITableView
        }

    } catch {
        print("Error occur")
        // TODO 
        // handle error here
    }
}