views:

51

answers:

2

I have a list of items with a plus button in the navigation bar that opens up a modal window containing a table of the models attributes, that displays a form when the table items are clicked (pretty standard form style). For some reason if I click the plus button to open the form to create a new model, then immediately click the done button, the person model is saved. The action linked to the done button does nothing but call on a delegate method notifying the personListViewController to close the window.

The apple docs do state that the model is not saved after calling the insertNewObjectForEntityName: ...

Simply creating a managed object does not cause it to be saved to a persistent store. The managed object context acts as a scratchpad.

I am at a loss to why this is happening, but every time I click the done button I have a new blank item in the original tableView.

I am using SDK v3.1.3

// PersonListViewController - open modal window
- (void)addPerson {
    // Load the new form
    PersonNewViewController *newController = [[PersonNewViewController alloc] init];
    newController.modalFormDelegate = self;

    [self presentModalViewController:newController animated:YES];
    [newController release];
}

// PersonFormViewController
- (void)viewDidLoad {
    [super viewDidLoad];

    if ( person == nil ) {
        MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    self.person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" 
                                                    inManagedObjectContext:appDelegate.managedObjectContext];
    }

    ...

    UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
                                                                              target:self action:@selector(done)];
    self.navigationItem.rightBarButtonItem = doneButton;
    [doneButton release];
}

- (IBAction) done {
    [self.modalFormDelegate didCancel];
}

// delegate method in the original listViewController
- (void) didCancel {
    [self dismissModalViewControllerAnimated:YES];
}
+1  A: 

If you are using a fetched result controller, it updates itself based on the state of the context. The store is not updated until you call save: on the context, but the context itself absolutely is (it would make no sense otherwise).

Also, by default, when you close your application (if you used the CoreData template), it will save the current context, so these changes will persist.

If you don't want your table view to pick up the changes, you must delete the new entity from the context before returning to the previous view, or use two separate contexts (I urge you /not/ to chose this method unless you understand 100% how CoreData works).

Jason Coco
Makes sense. Thanks for the help.
chris
+1  A: 

You're misunderstanding the documentation.

Think of the application's data as a text document. A user can open the text document and type or delete things in it and it appears changed on screen but the file containing the text hasn't been saved yet. This is what's happening with your original table view: it's a visual presentation of the state of the data at that specific moment.

Just as a user may type into a text document without the the changes being written to file, the same thing is happening with your application's data. Every time you click on the plus button, a new model is created and the application is correctly representing it visually. However, the disk storage hasn't written a single thing.

The default Core Data application template from Xcode will save (write the data content to storage) when the user quits the app, making any data changes permanent. Until then, any changes are only affect what's in memory.

Giao