NSManagedObject's hasChanges is true while changedValues is empty

流过昼夜 提交于 2020-06-10 02:53:23

问题


I am trying to observe individual NSManagedObject changes on NSManagedObjectContextWillSaveNotification:

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

The problem is that hasChanges is true while object.changedValues is empty, thus wrongly (?) triggering managedObjectWasUpdated:.

I'm trying to understand why this is the case and if I should better check object.changedValues.count before calling managedObjectWasUpdated:.


isInserted and isDeleted are both false.


回答1:


I encountered the same issue. Instead of getting the flags, I just checked if changedValues() is empty.

For Swift:

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



回答2:


In my experience, if the entity already existed, you loaded it and then you set a value to a property that is equal to its previous value, then the record will be marked as updated, hasChanges will return YES, and changedValues will be empty. When you save the context, what gets updated is a special Core Data column called Z_OPT, which refers to the number of times an entity has been updated. For these situations you can do something like this before saving:

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

in order to don't even update the Z_OPT value.




回答3:


According to doc, hasChanges will return YES if the receiver has been inserted, has been deleted, or has unsaved changes, otherwise NO.

In your case, you can check isInserted, isUpdated, isDeleted flag to find what happened to your managed object. changedValues only show the properties that have been changed since last fetching or saving the receiver.




回答4:


From iOS 7 you can also use hasPersistentChangedValues instead of changedValues. I think this performs better.




回答5:


Do you have any transient attributes on your entity? I am seeing the behavior you describe, and I've written some test code that shows that modifying a transient attribute causes hasChanges to return true, while changedValues is empty.

You can avoid this behavior by using setPrimitiveValue:forKey: to modify your transient attribute or the equivalent method generated by Core Data (setPrimitiveFoo: for an attribute named foo). You could also implement the transient attribute's setter to do this for you.



来源:https://stackoverflow.com/questions/26293852/nsmanagedobjects-haschanges-is-true-while-changedvalues-is-empty

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!