I have been trying to figure out this problem for 2 days now. I keep getting an error when I try to save.
//self.data is NSManagedObject. kAppDelegate.moc is the managed object context.
self.data = [NSEntityDescription insertNewObjectForEntityForName:@"Data"
inManagedObjectContext:kAppDelegate.moc];
[self.data setValue:[NSNumber numberWithBool:NO] forKey:@"isit"];
[self.data setValue:@"" forKey:@"name"];
NSError *error;
if(![self.data.managedObjectContext save:&error])
{
NSLog(@"Save did not complete successfully. Error: %@",
[error localizedDescription]);
}
When I run it though, this appears in the console:
"CoreData: error: Mutating a managed object 0x10935d4c0 (0x10935d420) after it has been removed from its context."
And this:
Save did not complete successfully. Error: (null)
I can't figure out why this is happening, or why the error is "null".
Given this error:
2015-07-06 06:15:05.124 xxx[3609:796500] CoreData: error: Mutating a managed object 0x17423d3e0 (0x1740d0450) after it has been removed from its context.
Found:
In my case; a trace of the initialization sequence (using breakpoints and log message class_initial:%B:%H) revealed that I was creating the context twice. My solution was to simply redirect the redundant call to self.managedObjectContext. I may take time at a later point to track down and eliminate the redundant logic.
Initial Results:
Final Results
Recommendation:
For others having this problem, I recommend a close inspection of your Core Data Stack's initialization sequence. A context may be created twice or the managed object might be getting deleted.
There is another way to provoke the "CoreData: error: Mutating a managed object ... after it has been removed from its context." message.
When the update bubbles up to the foreground thread it invalidates your object. You need to detect that and retrieve the new version.
Hold a weak reference in a cache object. Then write a getter that checks that cache object for nil and retrieves the new version of the object.
weak var cachedObject: NSManagedObject?
var object: NSManagedObject {
get {
objc_sync_enter( self )
defer {
objc_sync_exit( self)
}
guard nil == cachedObject else {
return cachedObject!
}
guard let object = // **** retrieve object here ****
fatalError( "managed object does not exist" )
}
cachedObject = object
return cachedObject!
}
set {
cachedObject = newValue
}
}
Or, you could just retrieve the object every time in the getter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With