核心数据 NSFetchedResultsController 在设备上执行 batchUpadate 后未更新,但在模拟器上正常

Posted

技术标签:

【中文标题】核心数据 NSFetchedResultsController 在设备上执行 batchUpadate 后未更新,但在模拟器上正常【英文标题】:Core Data NSFetchedResultsController not updated after a batchUpadate on the device but ok on simulator 【发布时间】:2015-08-25 05:08:39 【问题描述】:

我有一个 NSFetchedResultsController 来管理我的 UITableView 数据源。

我正在尝试使用NSBatchUpdateRequest 修改名为amountToComputeNSManagedObject 的属性。所以我创建了批量更新:

let batchUpdate = NSBatchUpdateRequest(entityName: "MyEntity")
batchUpdate.propertiesToUpdate = ["amountToCompute" : newAmount]
batchUpdate.resultType = .UpdatedObjectIDsResultType

我执行它:

var batchError: NSError?
let batchResult = managedContext.executeRequest(batchUpdate, error: &batchError) as! NSBatchUpdateResult?

为了更新我当前的托管上下文,我更新了 managedContext 中的每个 managedObject 并执行了一个新的 fetchedResultsController 提取:

if let result = batchResult 
    let objectIDs = result.result as! [NSManagedObjectID]

    for objectID in objectIDs 
        let managedObject: NSManagedObject = managedContext.objectWithID(objectID)

        if !managedObject.fault 
            managedContext.refreshObject(managedObject, mergeChanges: true) 
        

        if !fetchedResultsController.performFetch(&error) 
            println("error: + \(error?.localizedDescription), \(error!.userInfo)")
        
    

我实现了委托NSFetchedResultsControllerDelegate 的一些方法来管理NSFetchedResultsController 发送的结果的变化:

func controllerWillChangeContent(controller: NSFetchedResultsController) 
    tableView.beginUpdates()


    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) 

        switch type 
        ... 
        case .Update:
            reloadRowsAtIndexPaths([indexPath!], animation: reloadRowsWithAnimation)
            let myManagedObject = anObject as! MyManagedObject
            println("update : \(myManagedObject.amountToCompute)")
        ...
        
    

    func controllerDidChangeContent(controller: NSFetchedResultsController) 
        tableView.endUpdates()
    

我在我的 8.4 ios 模拟器上运行该应用程序,一切正常。 println("update : \(myManagedObject.amountToCompute)") 打印新值。

我在我的 iPhone 6 8.4.1 上运行该应用程序并且值没有更新,println("update : \(myManagedObject.amountToCompute)") 打印旧值。新值已正确保存,但更改未出现在我的表格视图中,而它们在模拟器上显示。

怎么了?无论我是在模拟器上还是在我的设备上,怎么会有所不同。版本并不完全相同,但我怀疑 Apple 在上次更新中触及了 Core Data 架构。

【问题讨论】:

在设备上,您是否获得了 Move 更改类型 (NSFetchedResultsChangeMove)? 不,模拟器上也没有。 【参考方案1】:

这是一个不寻常但已知的问题,我遇到了自己并花了几天时间拔头发,直到找到了这篇对我有用的博客文章。

https://stevenpsmith.wordpress.com/2011/08/12/nsfetchedresultscontroller-and-core-data-managed-object-updates/

归结为添加这行代码将过时间隔设置为零:

[上下文 setStalenessInterval:0];

如果我没看错你的帖子,你也会遇到同样的问题。 :)

【讨论】:

天哪!你的昵称很适合你,你是老板!!!我花了很多年才找到解决方案!非常感谢! 知道为什么它在模拟器上工作吗? 是的,实际上,在 VM 环境中没有实际的硬件延迟,即 StalenessInterval 为 0,因为模拟器不断轮询,至少与总线速度一样快。 它不再适用于 xcode 7。这次他们用 Core Data 搞砸了!谢谢苹果!

以上是关于核心数据 NSFetchedResultsController 在设备上执行 batchUpadate 后未更新,但在模拟器上正常的主要内容,如果未能解决你的问题,请参考以下文章

如何按创建 UITableViewCell 时计算的值对 UITableView 进行排序?

启动 Core Data 应用程序时在后台配置 NSFetchedResultsController

大数据核心技术都有哪些

哪里不使用核心数据?是不是可以将核心数据用作 MySql 之类的数据库?

使用 MKMapView、核心位置和核心数据

大数据三大核心技术:拿数据、算数据、卖数据!