Search code examples
objective-cmacoscocoacore-datansmanagedobjectcontext

When does Core Data save the managed object context by itself?


I have a OS X 10.9 only, non-document application.
When i do not call -save: explicitly on my managed object context, when does Core Data call -save: by itself?
Up to now, i have only found out, that it saves before quitting the application.


Solution

  • if you checked "Core Data" when creating a new Xcode project, this should be found i your app delegate:

    - (void)applicationWillTerminate:(UIApplication *)application {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        // Saves changes in the application's managed object context before the application terminates.
        [self saveContext];
    }
    
    #pragma mark - Core Data Saving support
    
    - (void)saveContext {
        NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
        if (managedObjectContext != nil) {
            NSError *error = nil;
            if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
                // Replace this implementation with code to handle the error appropriately.
                // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }
    }
    

    So when terminating the app it will explicitly call save.

    The right answer is: The context will only be saved when you call save: on it. But with the xcode template this is set up for you.


    The code above is for iOS, for Mac OS X it looks like

    - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
        // Save changes in the application's managed object context before the application terminates.
    
        if (!_managedObjectContext) {
            return NSTerminateNow;
        }
    
        if (![[self managedObjectContext] commitEditing]) {
            NSLog(@"%@:%@ unable to commit editing to terminate", [self class], NSStringFromSelector(_cmd));
            return NSTerminateCancel;
        }
    
        if (![[self managedObjectContext] hasChanges]) {
            return NSTerminateNow;
        }
    
        NSError *error = nil;
        if (![[self managedObjectContext] save:&error]) {
    
            // Customize this code block to include application-specific recovery steps.              
            BOOL result = [sender presentError:error];
            if (result) {
                return NSTerminateCancel;
            }
    
            NSString *question = NSLocalizedString(@"Could not save changes while quitting. Quit anyway?", @"Quit without saves error question message");
            NSString *info = NSLocalizedString(@"Quitting now will lose any changes you have made since the last successful save", @"Quit without saves error question info");
            NSString *quitButton = NSLocalizedString(@"Quit anyway", @"Quit anyway button title");
            NSString *cancelButton = NSLocalizedString(@"Cancel", @"Cancel button title");
            NSAlert *alert = [[NSAlert alloc] init];
            [alert setMessageText:question];
            [alert setInformativeText:info];
            [alert addButtonWithTitle:quitButton];
            [alert addButtonWithTitle:cancelButton];
    
            NSInteger answer = [alert runModal];
    
            if (answer == NSAlertFirstButtonReturn) {
                return NSTerminateCancel;
            }
        }
    
        return NSTerminateNow;
    }
    

    There the save: method is called, too.