4

I create a temporary NSManagedObject and associate it with the main NSManagedObjectContext. I need be able to treat it as a fully functioning object (perform fetch requests, etc) inside the context and thus cannot create it without an associated context. I include logic to delete the managed object in ViewWillDisappear under the condition that a new view controller was not just pushed onto the stack:

- (void)viewWillDisappear:(BOOL)animated { 
  [super viewWillDisappear:animated];

  NSArray *viewControllers = self.navigationController.viewControllers;
  if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
    // View is disappearing because a new view controller was pushed onto the stack
  } else  {
    // View is disappearing for some other reason
    [self.community.managedObjectContext deleteObject:self.community];
  }
}

This seems to properly delete the managed object in all cases except for the application quitting. I tried deleting the object in viewDidUnload but it seems the method is not called upon the application quitting. I have considered creating a second managed object context, but want to avoid the major overhead if possible.

Thanks, Graham

4 Answers4

1

Keep the managed object in a shared instance of as a class variable so it is reachable from more places in your application then the class you handle it from.

There are two scenarios:

1) before iOS 4.0
When the applicationWillTerminate you can delete the object from the context.

2) Since iOS 4.0.
When your application will go in the background and you will kill the process (the hard way, with the 'kill app bar'), the applicationWillTerminate will never get called. You cannot recognize this event. So your screwed with the applicationWillTerminate.
You will have to solve it like this:
- applicationWillEnterBackground: -> save an identifier to the managed object in the userdefaults or a simple file.
- applicationDidFinishLaunching: -> if file exists, delete the managed object it is referring to.
- applcationWillEnterForeground: -> delete the file.

Now when your app goes into background and comes back, you will have the same state and the object will not be deleted. When you kill your app, the object will be deleted on startup.

Mats Stijlaart
  • 5,058
  • 7
  • 42
  • 58
  • 1
    Thanks Mats - that logic works like a charm! I would just like to point out that I used applicationWillResignActive: to save the object's URI to the NSUserDefaults (I don't believe an applicationWillEnterBackground: method exists). If you are looking for details on how to save an identifier to a managed object, check out this post ["Safely fetching an NSManagedObject by URI"](http://cocoawithlove.com/2008/08/safely-fetching-nsmanagedobject-by-uri.html). Note that since that article was written, the method existingObjectWithID:error: has been added to NSMangedObjectContext –  Mar 03 '11 at 17:36
  • Ok Graham. I think i meant appliationDidEnterBackground. But willResign will also work. Good luck. – Mats Stijlaart Mar 04 '11 at 07:34
0

I understand you already have a working answer, but if your object is truly temporary, and will never be saved, why not just create it in a child context? It will still have all the fetch visibility you desire, but will never get pushed to the other contexts, nor saved in the physical database until you call save on the context.

If you never call save, the temporary object will never be saved, thus truly making it temporary.

And the kicker... you don't have to write any extra code at all or handle all the "exiting" conditions since it never got put into the actual database.

Jody Hagins
  • 27,943
  • 6
  • 58
  • 87
0

In your app delegate, implement the -applicationWillTerminate: method. This method is called right before your application is purged from memory and you can delete the temporary managed object there.

Simon Goldeen
  • 9,080
  • 3
  • 36
  • 45
0

applicationWillTerminate and its multi-tasking cousins work, but since you are only deleting a single object the best way is to save your context after every delete.

Just call - (BOOL)save:(NSError **)error:

[self.community.managedObjectContext deleteObject:self.community];
NSError *error = nil;
[self.community.managedObjectContext save:&error];
elitalon
  • 9,191
  • 10
  • 50
  • 86
amattn
  • 10,045
  • 1
  • 36
  • 33