如何用后台线程中的新过滤器谓词重新加载NSFetchedResultsController?

时间:2016-11-19 22:38:55

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

我有UISearchBar并尝试在我的基础中添加一些过滤器,但是当我尝试用新的谓词重新加载我的NSFetchedResultsController时,有时重新加载包含大约10秒(对于一个谓词),而在其他时间只有2秒用于这个谓词。在Predicates中使用的Core Data中的所有属性都被编入索引。 为什么会发生这种情况以及如何解决这个问题?

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

1 个答案:

答案 0 :(得分:0)

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

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

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