使用带有NSBatchDeleteRequest的NSFetchedResultsController

时间:2016-11-13 15:11:30

标签: ios swift core-data nsfetchedresultscontroller nsbatchdeleterequest

我在使用NSBatchDeleteRequest后从NSFetchedResultsControllerDelegate获得准确更新时遇到问题,这些更改是作为更新类型而不是didChange委托方法上的删除类型。有没有办法让更改作为删除进入? (我有不同的删除与更新方案)。

删除请求: (使用调用者提供的私有上下文)

fileprivate class func deletePeopleWith(ids: Set<Int>, usingContext context: NSManagedObjectContext) {

    let fr: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Person")

    var predicates: [NSPredicate] = []
    ids.forEach {

        predicates.append(NSPredicate(format: "id = %ld", $0))
    }

    fr.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates)

    let dr = NSBatchDeleteRequest(fetchRequest: fr)
    dr.affectedStores = context.parent?.persistentStoreCoordinator?.persistentStores

    do {

        try context.parent?.execute(dr)
        context.parent?.refreshAllObjects()
        print("Deleting person")

    } catch let error as NSError {

        let desc = "Could not delete person with batch delete request, with error: \(error.localizedDescription)"
        debugPrint(desc)
    }

}

结果:

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {

    DispatchQueue.main.async {

        let changeDesc = "Have change with indexPath of: \(indexPath), new index path of: \(newIndexPath) for object: \(anObject)"
        var changeType = ""
        switch type {

        case .delete:
            changeType = "delete"

        case .insert:
            changeType = "insert"

        case .move:
            changeType = "move"

        case .update:
            changeType = "update"

        }

        print(changeDesc)
        print(changeType)
    }

}

印刷:

Have change with indexPath of: Optional([0, 0]), new index path of: Optional([0, 0]) for object: *my core data object*
update

3 个答案:

答案 0 :(得分:6)

来自Apple的documentation

  

批量删除比在代码中自己删除Core Data实体运行得更快,因为它们在SQL级别的持久性存储本身中运行。作为此差异的一部分,持久性存储上实现的更改不会反映在当前内存中的对象中。

     

执行批量删除后,删除内存中已从持久性存储中删除的所有对象。

有关处理NSBatchDeleteRequest删除的对象的信息,请参阅Updating Your Application After Execution部分。

答案 1 :(得分:1)

由于cat sample.txt label_annotations { mid: "/m/01yrx" description: "Cat" score: 0.9895679950714111 topicality: 0.9895679950714111 } label_annotations { mid: "/m/0307l" description: "Felidae" score: 0.9541760087013245 topicality: 0.9541760087013245 } label_annotations { mid: "/m/01l7qd" description: "Whiskers" score: 0.953809380531311 topicality: 0.953809380531311 } label_annotations { mid: "/m/01k74n" description: "Facial expression" score: 0.9447915554046631 topicality: 0.9447915554046631 } 删除了persistentStore级别(在磁盘上)的托管对象,所以更新当前上下文(内存中)的最有效方法是通过在上下文上调用NSBatchDeleteRequest,如下所示:

refreshAllObjects()

无需重新获取所有对象或func batchDelete() { if let appDelegate = UIApplication.shared.delegate as? AppDelegate { let context = appDelegate.persistentContainer.viewContext if let request = self.fetchedResultsController.fetchRequest as? NSFetchRequest<NSFetchRequestResult> { let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: request) do { try context.execute(batchDeleteRequest) // performs the deletion appDelegate.saveContext() context.refreshAllObjects() // updates the fetchedResultsController } catch { print("Batch deletion failed.") } } } }

答案 2 :(得分:0)

这是样本,对我有用。但我没有找到如何使用动画更新删除,因为NSFetchedResultsControllerDelegate没有触发。

@IBAction func didPressDelete(_ sender: UIBarButtonItem) {
        let managedObjectContext = persistentContainer.viewContext
        let request = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: Record.self))
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: request)

        do {
            // delete on persistance store level
            try managedObjectContext.execute(deleteRequest)

            // reload the whole context
            managedObjectContext.reset()
            try self.fetchedResultsController.performFetch()
            tableV.reloadData()
        } catch {
            print("")
        }
    }

Thanks