RyanJM
RyanJM

Reputation: 7068

How to delete new objects from NSManagedObjectContext

Ok, lets start with the code. I am looping through a returned array of dictionaries and creating (or updating) objects based on them. In this method I'm trying find or create a new entity. And then if the object is supposed to be deleted, I'd like to do so and not waste time updating it with the new information.

- (void)updateOrCreateObjectWith:(NSDictionary*)dictionary {
    RKManagedObjectStore *objectStore = ((MyAppDelegate*)[[UIApplication sharedApplication] delegate]).objectStore;

    id updateObject = (NSManagedObject*)[objectStore findOrCreateInstanceOfEntity:[resource entity] withPrimaryKeyAttribute:@"myID" andValue:[dictionary objectForKey:@"id"]];

    [updateObject setMyID:[dictionary objectForKey:@"id"]];

    // if marked for deletion, delete it now
    if ([[dictionary objectForKey:@"deleted_at"] isKindOfClass:[NSString class]]) {
        if ([updateObject isNew]){
            NSError *error = nil;
            [objectStore.managedObjectContext save:&error];
            if (error) {
                NSLog(@"error saving before delete: %@",error);
                return;
            }
//          [objectStore.managedObjectContext deleteObject:updateObject];
//          [objectStore.managedObjectCache delete:updateObject];  
        }
        else {
            [objectStore.managedObjectContext deleteObject:updateObject];            
        }
        return;
    }

    [updateObject updateWith:dictionary];
}

The part to be aware of is the deleted_at section with the (1) save section, (2) delete object from context, and (3) delete object from cache. I have tried a few combinations of those three but I don't get the desired results.

If I delete it from the cache (just #3):

If I delete it from the managed context (just #2) I get:

NSUnderlyingException=Cannot update object that was never inserted.

Since it was never inserted, I thought I'd save it and then delete it (#1 and #2), but then I get:

*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xed27810 <x-coredata://4EE6AD5A-CC34-460A-A97A-0909454126A4/User/p166>''

So what is the proper way to remove a "new" object from NSMangedObjectContext?

Upvotes: 2

Views: 2762

Answers (2)

Evan Cordell
Evan Cordell

Reputation: 4118

It's easier to get the RKManagedObjectStore instance with [[RKObjectManager sharedManager] objectStore] (assuming you want the shared one, which it seems like you do since you're calling your app delegate).

Check for the deleted_at key before you ever create an NSManagedObject. This code assumes you're converting to type Resource, which is a subclass of NSManagedObject. It's untested but should give you an idea of what you should be doing.

- (void)updateOrCreateObjectWith:(NSDictionary*)dictionary {
RKManagedObjectStore *objectStore = [[RKObjectManager sharedManager] objectStore];

    //get a reference to the object
    Resource *resource = [Resource findFirstByAttribute:@"myID" withValue:[dictionary objectForKey:@"id"]];

    //see if "deleted_at" exists in dictionary
    if ([[dictionary objectForKey:@"deleted_at"] isKindOfClass:[NSString class]])
    {
        //check to see if object exists in the context
        if(resource)
        {
            //if it exists, delete it
            [objectStore.managedObjectContext deleteObject:resource];
        }
    } else {
        //no "deleted at", so create the object
        if (!resource) {
            //resource is nil (it doesn't exist in the context), so we need to create it
            resource = [Resource object];
        }
        [resource updateWith:dictionary];
    }

    NSError *error = nil;
    [objectStore.managedObjectContext save:&error];
    if (error) {
        NSLog(@"error saving before delete: %@",error);
    }
}

Upvotes: 2

Costique
Costique

Reputation: 23722

You want to avoid creating managed objects unless necessary. The best strategy is to follow this pseudo code:

NSManagedObject *existingObject = ...; // fetch the object
if (existingObject) {
    if (deleted) {
        [self.managedObjectContext deleteObject: existingObject];
    }
} else {
    if (!deleted) {
        // create the object, insert it into the MOC, set the object properties
    }
}

Upvotes: 1

Related Questions