【问题标题】:Why does storing a reference to an NSManagedObject prevent it from updating?为什么存储对 NSManagedObject 的引用会阻止它更新?
【发布时间】:2017-11-04 05:31:06
【问题描述】:

这个问题的阶段性不好,但这可以在代码中更好地解释。

我们有一个核心数据堆栈,其中包含 Marcus Zarra 在此处定义的私有和主要上下文:http://martiancraft.com/blog/2015/03/core-data-stack/

我们调用一个单独的类来执行获取请求(主上下文)并返回一个 NSManagedObjects 数组:

NSArray *ourManagedObjects = [[Client sharedClient].coreDataManager fetchArrayForClass:[OurObject class] sortKey:@"name" ascending:YES];

然后我们进行一些处理并存储一个引用:

self.ourObjects = processedManagedObjects

我们的视图包含一个 UITableView,这些数据用于填充它,效果很好。

我们更改 CMS 上的数据,在 UITableView 上拉动以刷新以触发同步(私有上下文),然后调用相同的函数来检索更新的数据。但是,即使当我直接检查 sqlite db 时,提取请求返回的数据与以前完全相同,但它包含新数据。要显示新值,我必须重新加载应用程序。

我发现如果我不将已处理的ManagedObjects 分配给self,则获取请求确实会返回正确的数据,因此看起来持有对NSManagedObject 的引用会阻止它从主上下文获取新数据。但是我不知道为什么会这样。

澄清一下,我们很确定我们的核心数据堆栈没有任何问题,即使这些托管对象没有被更新,其他的都在正常更新,只是我们存储本地引用的这个。

【问题讨论】:

    标签: ios objective-c core-data


    【解决方案1】:

    听起来是这样的:

    • 当通过不同的托管对象上下文进行更改时,托管对象不会自动更新自身以反映持久存储中的最新数据。
    • 因此,如果您保留对对象的引用,它们将保留已有的任何数据。
    • 另一方面,如果您不保留引用而是重新获取它们,您将获得新数据,因为没有托管对象与旧数据一起闲置。

    你有几个选择:

    • 您可以使用refresh(_, mergeChanges:) 方法或refreshAllObjects() 保留引用并让您的上下文刷新托管对象。
    • 如果它对您的应用有意义,请使用 NSFetchedResultsController 并使用其委托方法来接收更改通知。
    • 不要保留参考。

    第一个可能是最好的——refreshAllObjects() 可能是你想要的。根据您应用的其他详细信息,其他选项可能会更好。

    【讨论】:

    • 刷新所有对象让它工作,太棒了!我认为调用此方法会对性能产生影响,但还有其他缺点吗?
    • 潜在的缺点是如果您刷新的对象有任何未保存的更改,您可能会丢失它们。使用refresh(_, mergeChanges:),您可以根据第二个参数进行控制。使用refreshAllObjects(),您将丢失刷新对象上未保存的更改。
    • 好的,谢谢。所有更改都在私有上下文中进行,并且仅在保存完成后执行获取请求。
    【解决方案2】:

    尝试将获取请求的shouldRefreshRefetchedObjects 属性设置为true。根据the documentation

    默认情况下,当您获取对象时,它们会保持其当前属性值,即使持久存储中的值已更改。使用参数 true 调用此方法意味着执行 fetch 时,将使用持久存储中的当前值更新已获取对象的属性值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      • 2016-10-21
      • 2011-01-02
      相关资源
      最近更新 更多