1

I am using Core Data in my application.

My problem is that Entities (NSManagedObject) are persisting their state whether or not I call Save on NSManagedObjectContext, only condition is that the application is active. When I terminate application and again run it, all entities retains the last properties or changes made before the last "Save on NSManagedObjectContext" had been called.

Eg. I am having OpenViewController and FormOpenViewController.

FormOpenViewController works on (Form *) entity (NSManagedObject).

OpenViewController calls FormOpenViewController and fetch (Form *) object from database and passes it to FormOpenViewController's (Form *)form object.

In viewDidLoad of FormOpenViewController I change the value of one property "editable" of (Form *)form object to "YES".

i.e. FormOpenViewController.m

- (void)viewDidLoad
{
     // changed the editable property of form to yes from no
     if([formEditData.editable boolValue] == NO)
     {
          form.editable = [NSNumber numberWithBool:YES];
     }

}

-(void)saveData
{
    [[shareInstance delegate].managedObjectContext save:nil];
    [shareInstance delegate].arrForder = [[ipegsClient shareInstance ] getLoginUser].folders.allObjects;
}

So now If I go back to OpenViewController without calling saveData method, and again come to FormOpenViewController then control does not go into if block, it means it form object is now having "editable" property as "YES" which should be "NO" because till I have not "saveData function".

UPDATE:

I am creating new instance of FormOpenViewController each time when I call it or present it. And also fetching new (Form *) form object each time from database before calling FormOpenViewController.

EDIT:

calling following function in applicationWillTerminate:

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != 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.

            abort();
        }
    }
}

Does anyone know why this is happening?

Thanks in advance. correct me if I am going wrong somewhere.

ViruMax
  • 1,216
  • 3
  • 16
  • 41
  • Please give some more details...How are you going back? How are you passing the form object to the FormOpenViewControlooer? Are you re-initializing the form at each load? Do you maintain reference to the form in OpenViewContoroller? – Yoshkebab Nov 18 '14 at 07:29
  • This is how coredata behaves! The changes you make to your objects are always "saved in memory, but not to coredata". If you are only having one context, you should only need to save it when you quit your application. – ullstrm Nov 18 '14 at 07:32
  • @Spoek But if each time I am passing new (Form *) form object(fetched from database) , changes made to previous one should not be present as I have not called save on context. – ViruMax Nov 18 '14 at 07:35
  • But the changes is in fact still there, right? There's no such thing as "Should not" when we talk about things which are out of our control. This is at least how I've interpreted the core data API when having only one context. And it seems I am correct. – ullstrm Nov 18 '14 at 07:37
  • @Spoek might be you are right, but I don't know then why I am getting old values when I terminate and open application again? – ViruMax Nov 18 '14 at 07:56

1 Answers1

8

This is how core data works.

Think of the managed object context as an in-memory scratchpad for any changes you're making. When you change your objects, that change is "real" for as long as you are using that context.

If you save the context, those changes are written up to the next level, which is either a parent context, or your persistent store on disk.

If you destroy the context without saving, those changes are lost.

If you want to revert or undo changes made during a particular session then the simplest way is to create a child context and pass this to your editing view controller. If you then "cancel" the editing view controller, just destroy the child context and your changes will be lost. Otherwise, save the context and they'll pass up to the main context.

So, terminating the app without saving the context means that the next time you start up, the context is built from the data in the persistent store, which didn't have your changes written to it.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • You have mentioned that if you "cancel" editing you need to destroy the context. If the context is not destroyed explicitly will the changes be lost or will they persist? – ViruMax Nov 18 '14 at 08:41
  • 1
    If the context is kept around then the changes will stay _within that context_. They will not be present in the parent context. Normally you'd create a child context and pass this to the editing view controller, which has a strong reference to it. When the editing view controller is dismissed, the editing context goes with it because nothing else has a strong reference – jrturton Nov 18 '14 at 10:20