For the life of me I can't work this one out, but CoreData keeps throwing me an error.
Cannot delete object that was never inserted.
Here is the jist of my app cycle:
1/ Push ViewController.
2/ Get managed object context from app delegate.
FLAppDelegate *appDelegate = (FLAppDelegate *)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = appDelegate.managedObjectContext;
3/ Check if Session
exists.
4/ No Session
exists, create a new one.
self.session = nil;
self.session = [NSEntityDescription insertNewObjectForEntityForName:@"Session" inManagedObjectContext:self.managedObjectContext];
//Set attributes etc...
//Keep a reference to this session for later
[[NSUserDefaults standardUserDefaults] setURL:self.session.objectID.URIRepresentation forKey:kKeyStoredSessionObjectIdUriRep];
[[NSUserDefaults standardUserDefaults] synchronize];
NSError *error = nil;
if (![self.managedObjectContext save:&error])
{
//Handle error if save fails
}
5/ Pop ViewController.
6/ Return to ViewController.
7/ Again, check if Session
exists.
8/ A Session
is found! (By looking at NSUserDefaults
for the one we stored to later reference). So I get Session
I created earlier then give the user a choice to delete that one and start fresh or continue with that one.
NSURL *url = [[NSUserDefaults standardUserDefaults] URLForKey:kKeyStoredSessionObjectIdUriRep];
if (url) //Found existing flight session
{
NSManagedObjectID *objId = [self.managedObjectContext.persistentStoreCoordinator managedObjectIDForURIRepresentation:url];
NSManagedObject *obj = [self.managedObjectContext objectWithID:objId];
self.session = (Session *)obj;
//Ask the user if they want to continue with this session or discard and start a new one
}
9/ Choose to delete this Session
and start a new one.
10/ Problem begins here! I delete the reference I am keeping to this Session
as it is no longer relevant and try to delete the object then save those changes.
[[NSUserDefaults standardUserDefaults] removeObjectForKey:kKeyStoredSessionObjectIdUriRep];
[[NSUserDefaults standardUserDefaults] synchronize];
[self.managedObjectContext deleteObject:self.session];
NSError *error = nil;
if (![self.managedObjectContext save:&error])
{
//Error!
}
11/ There we have it, when I try to run the save method, it crashes and throws an error: NSUnderlyingException = "Cannot delete object that was never inserted.";
I have no clue why it says so, as I appear to save the object whenever I create one and create the reference, retrieve the object from that reference but then deleting just breaks everything.
Table views have a built-in swipe to delete mechanic that we can draw upon to let users delete commits in our app. Helpfully, managed object context has a matching delete() method that will delete any object regardless of its type or location in the object graph.
The NSManagedObjectContext class isn't thread safe. Plain and simple. You should never share managed object contexts between threads. This is a hard rule you shouldn't break.
An object space to manipulate and track changes to managed objects.
The problem is in your step 4. In this step you
Session
The reason this fails is that when you create a new managed object, it has a temporary object ID that is only valid until you save changes. As soon as you save changes, it gets a new, permanent object ID. You're saving the temporary object ID, but when you look it up later it's not valid any more.
You can fix this just by changing the order of operations in step 4 so that you:
Session
Session
's object ID to user defaultsThis way you'll have a permanent ID when you save the value to user defaults.
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