swift - 如何在后台线程中使用新的过滤谓词重新加载 NSFetchedResultsController ?

标签 swift core-data uisearchbar grand-central-dispatch nsfetchedresultscontroller

我有 UISearchBar 并尝试在我的基础中附加一些过滤器,但是当我尝试使用新谓词重新加载 NSFetchedResultsController 时,有时重新加载大约需要 10 秒(对于一个谓词),而在其他时候,这个谓词仅需要 2 秒。核心数据中谓词中使用的所有属性均已建立索引。 为什么会发生这种情况以及如何解决这个问题?

fetchResultController代码

lazy var context: NSManagedObjectContext = {
    let appDelegate = (UIApplication.shared.delegate as? AppDelegate)
    return appDelegate!.managedObjectContext
}()

lazy var fetchedResultsController: NSFetchedResultsController<CardsBaseClass> = {
    let fetchRequest = NSFetchRequest<CardsBaseClass>(entityName: "CardsBase")
    let sortDescriptor = NSSortDescriptor(key: "cardName", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]

    fetchRequest.fetchBatchSize = 50
    fetchRequest.returnsObjectsAsFaults = false

    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.context, sectionNameKeyPath: nil, cacheName: nil)
    fetchedResultsController.delegate = self
    return fetchedResultsController
}()

UISearchBar方法

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    block?.cancel()
    var predicateArray = predicateArrayClass.arrayOfPredicates
    block = DispatchWorkItem {
        let predicate = NSPredicate(format: "\(self.searchPredicateName) contains[c] %@", searchText)
        predicateArray.append(predicate)
        self.fetchedResultsController.fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicateArray)
        print(self.fetchedResultsController.fetchRequest.predicate)
        self.connectFetchedRequest()
        DispatchQueue.main.async(execute: {
            self.tableView.reloadData()
        })
    }
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: block!)
}

最佳答案

您无法在后台线程上运行主线程 Core Data 托管对象上下文。

在 Core Data 中使用后台线程时,最好使用框架本身,而不是 GDC 或 DispatchQueue API。 Core Data 提供 block API 以及父上下文和子上下文的概念。我认为在您的代码中,您违反了这些 API 的主要原则:始终在其自己的线程上运行不同的上下文,反之亦然:不要在多个线程上运行任何上下文。

我建议创建一个子上下文并使用 performBlock 进行搜索。

关于swift - 如何在后台线程中使用新的过滤谓词重新加载 NSFetchedResultsController ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40698695/

相关文章:

ios - 核心数据加密类

ios - 没有已知的选择器混淆类方法

ios - iOS 导航栏中的搜索栏在触摸时会稍微向下移动

ios - NSTimer scheduledTimerWithTimeInterval - 不调用函数

ios - 删除所有 CKShare 记录

ios - UICollectionView | UICollectionView |电池可重复使用

ios - 使用布局 anchor 将自定义导航栏项目居中

swift - 如何在 SpriteKit 游戏中保存游戏进度

ios - iOS中的数据模型版本编译器(MOMC)错误

swift - UINavigationBar 中的 searchBar isHidden 后获取标题