Reputation: 1069
how to discard CoreData changes made to an instance of NSManagedObject when POST/PUT request of this object fails in RKObjectManager?
NSManagedObject *object = ...;
[object setValue:@"test" forKey: @"test"];
[[RKObjectManager sharedManager] postObject:object
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { NSLog(@"success, nothing to do"); }
failure:^(RKObjectRequestOperation *operation, NSError *error) {
// I want to discard changes made to object here
}
UPDATE: RestKit 0.20
Upvotes: 15
Views: 4953
Reputation: 1089
An alternative solution is to refresh the values yourself.
The refresh method from the NSManagedObjectContext
can cause issues if you have more than one reference to an object, and especially if another class is doing KVO on properties. Upon refresh you will get objects that are faulted (all properties are nil) but that are in a broken state, receiving the error message _cd_rawData but the object is not being turned into a fault
when you try to access any properties.
Here is the alternative if you don't want to use a separate context and NSUndoManager
:
extension NSManagedObject {
func revertToCommitedValues() {
changedValues().keys.forEach { (key) in
if let persistentValue = committedValues(forKeys: [key])[key] {
if persistentValue is NSNull {
setValue(nil, forKey: key)
}
else {
setValue(persistentValue, forKey: key)
}
}
}
}
}
Note that NSManagedObject
's changedValues
method does not reflect changes inside of relationships, so if you want a 'deep reset' you will have to call that method on each of your relationships
You can build on this method to only refresh certain properties, of course.
Upvotes: 0
Reputation: 3163
Swift solution:
import CoreData
extension NSManagedObject {
func cancelChanges() {
managedObjectContext?.refresh(self, mergeChanges: false)
}
}
Using:
object.cancelChanges()
Upvotes: 4
Reputation: 6011
I know nothing about RKObjectManager
, but in order to discard changes to NSManagedObject instance you could call:
[object.managedObjectContext refreshObject:object mergeChanges:NO]
This will discard all changes and turn the object into fault.
Upvotes: 46