【问题标题】:NSManagedObject's hasChanges is true while changedValues is emptyNSManagedObject 的 hasChanges 为 true 而 changedValues 为空
【发布时间】:2014-12-05 07:04:13
【问题描述】:

我正在尝试观察NSManagedObjectContextWillSaveNotification 上的个人NSManagedObject 变化:

- (void)managedObjectContextWillSave:(NSNotification *)notification
{
    for (NSManagedObject * object in self.mutableObservedManagedObjects)
    {
        if (object.hasChanges)
        {
            [self managedObjectWasUpdated:object];
        }
    }
}

问题是hasChanges 为真而object.changedValues 为空,因此错误地(?)触发managedObjectWasUpdated:

我正在尝试了解为什么会这样,以及是否应该在致电 managedObjectWasUpdated: 之前检查一下 object.changedValues.count


isInsertedisDeleted 都是假的。

【问题讨论】:

    标签: ios macos core-data nsnotificationcenter


    【解决方案1】:

    根据我的经验,如果实体已经存在,则加载它,然后将值设置为等于其先前值的属性,然后记录将被标记为已更新,hasChanges 将返回 YES ,而changedValues 将为空。当您保存上下文时,会更新一个名为 Z_OPT 的特殊核心数据列,它指的是实体已更新的次数。对于这些情况,您可以在保存之前执行以下操作:

    for (NSManagedObject *managedObject in context.updatedObjects.objectEnumerator) {
        if (!managedObject.changedValues.count) {
            [context refreshObject:managedObject mergeChanges:NO];
        }
    }
    

    为了不更新 Z_OPT 值。

    【讨论】:

    • 我相信这是最准确的答案。 hasChanges 基于Core Data 知道的一切(包括Z_OPT)。 changedValues() 正在报告您的实体的不同字段。在大多数情况下,应用程序可能更关心changedValues().isEmpty
    • 您可以使用NSManagedObject 引入的新属性,而不是检查changedValues.countvar hasPersistentChangedValues: Bool
    • 不幸的是,[NSManagedObjectContext -hasChanges] 仍然是true
    【解决方案2】:

    我遇到了同样的问题。我没有获取标志,而是检查了 changedValues() 是否为空。

    对于斯威夫特:

    if !managedObject.changedValues().isEmpty {
        // Has some changed values
    }
    

    【讨论】:

    • 这行得通,但仍然没有记录在案的行为,让人想知道苹果什么时候会打破它...... :(
    【解决方案3】:

    从 iOS 7 开始,您还可以使用 hasPersistentChangedValues 而不是 changedValues。我认为这表现得更好。

    【讨论】:

    • 确实hasPersistentChangedValues 是最好的选择。根据头文件的注释,如果任何持久属性未将 isEqual 与其上次保存的状态进行比较,hasPersistentChangedValues 将返回 YES。关系错误不会被不必要地解雇。这与现有的 -hasChanges 方法不同,后者是一个简单的脏标志,还包括瞬态属性。
    【解决方案4】:

    根据文档,hasChanges 将在接收器已插入、已删除或未保存更改时返回 YES,否则返回 NO。

    在您的情况下,您可以检查isInsertedisUpdatedisDeleted 标志来查找您的托管对象发生了什么。 changedValues 仅显示自上次获取或保存接收器以来已更改的属性。

    【讨论】:

    • 我遵循了文档,isInserted/isDeleted 都是假的,isUpdated 是真的,但没有 changedValues
    【解决方案5】:

    您的实体是否有任何临时属性?我看到了您描述的行为,并且我编写了一些测试代码,显示修改瞬态属性导致hasChanges 返回true,而changedValues 为空。

    您可以通过使用setPrimitiveValue:forKey: 修改您的瞬态属性或Core Data 生成的等效方法(setPrimitiveFoo: 用于名为foo 的属性)来避免这种行为。您还可以实现瞬态属性的设置器来为您执行此操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多