Why does Core Data take so long to save an object?

2019-06-05 02:19发布

I have a simple method in my entity category that adds custom methods to my subclassed NSManagedObject classes (which I don't touch because of automatic subclassing generating).

I have this method that deletes an object from the MOC and saves the context.

+ (void)deleteWishlist:(Wishlist *)wishlist
    inManagedObjectContext:(NSManagedObjectContext *)context
{

    [context deleteObject:wishlist];

    NSError *error;
    if(![context save:&error]) {
        NSLog(@"%@", error);
    } else {
        NSLog(@"Delete successful");
    }
}

I invoke this from one of my view controllers as so:

- (void)deleteWishlist:(Wishlist *)wishlist
{
    if(wishlist) {
        [Wishlist deleteWishlist:wishlist inManagedObjectContext:self.managedObjectContext];
    }
}

It gets called from a UI event handling method (the delegate tableView: commitEditingStyle: forRowAtIndexPath: method).

Now, this all works, but it's taking a long time to save the object...I don't know if this is the default behavior, but I want it to save immediately to persistent storage after deleting from the graph. I don't mind if I have to wait until it saves.

On the iOS simulator, if I hit 'stop' and then load my app back up again, the wishlist is still there. If I hit the home button, the app goes to background mode, and there it gets saved...but it seems like it's saving it twice. I don't know what it's doing the first time to be honest.

2013-05-29 00:45:14.819 App[29024:c07] [WishlistCDTVC setFetchedResultsController:] set
2013-05-29 00:45:14.820 App[29024:c07] [WishlistCDTVC performFetch] fetching all Wishlist (i.e., no predicate)
2013-05-29 00:45:15.755 App[29024:c07] Delete pressed
2013-05-29 00:45:16.666 App[29024:c07] NSManagedObjects did change.
2013-05-29 00:45:16.669 App[29024:c07] NSManagedContext did save.
2013-05-29 00:45:16.670 App[29024:c07] Delete successful
2013-05-29 00:45:19.119 App[29024:c07] NSManagedContext did save.

What I did: load up the wishlist VC, swipe to delete, confirm, it said 'delete pressed'. Deletes object from context, saves it (but apparently not here), then says delete successful (so no error), and then I hit the home button and it logs the last 'save' line, which DOES finally save to persistent storage. So why isn't the middle one saving?

1条回答
爷、活的狠高调
2楼-- · 2019-06-05 02:52

Easy fix, I now always save the NSManagedDocument after any changes to the context (I don't need undo functionality).

In my shared document handler class, I tell it to save on change notification.

- (void)objectsDidChange:(NSNotification *)notification
{
    #ifdef DEBUG
        NSLog(@"NSManagedObjects did change.");
    #endif
    [BSDocumentHandler saveDocument];
}

And saveDocument is just a class method:

+ (void)saveDocument
{
    UIManagedDocument *document = [[BSDocumentHandler sharedDocumentHandler] document];
    [document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:nil];
}

It now saves immediately and when I stop the simulator using stop, it now preserves the saves.

Furthermore, to avoid duplicate saves, I now removed all lines containing a managed object context save after creating, editing or deleting an object, and my shared document handler class manages all saves automatically, making for much less duplicated code.

My log is now much cleaner. This is performing a deletion. I invoke the VC that lists all items, swipe to delete, and confirm. It notices there was a change to the MOC and saves the document once (as expected).

2013-05-30 13:33:01.310 App[27167:c07] [ItemCDTVC setFetchedResultsController:] set
2013-05-30 13:33:01.312 App[27167:c07] [ItemCDTVC performFetch] fetching all Item (i.e., no predicate)
2013-05-30 13:33:04.735 App[27167:c07] NSManagedObjects did change.
2013-05-30 13:33:04.751 App[27167:c07] NSManagedContext did save.
查看更多
登录 后发表回答