I have two tableview controllers showing CoreData objects. One is a detail view (with sentences) one is an overview (with stories). Pick a Story -> See the Sentences.
It looks like I was over-releasing my managedObjectContext; I originally released it in both TableViewControllers in dealloc and got a crash every third time I went between the two controllers (Story -> Sentence -> Story -> Sentence -> Story -> Crash). Some debugging showed I was crashing in my App Delegate after this code in ViewDidLoad of both TableViewControllers:
if (managedObjectContext == nil)
{
managedObjectContext = [(StoryBotAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(@"After managedObjectContext: %@", managedObjectContext);
}
Some more research found this discussion which led me to believe it was a case of an over released ManagedObjectContext:
The second more prosaic issue is simply an overreleased NSManagedObject. Instruments ObjectAlloc tool should be able to help you.
So I removed [managedObjectContext release]; from my dealloc in TableViewController and now I have no leaks (according to Instruments) and no crash.
It looks like the problem is fixed, but here's the question:
I might be missing the point altogether, and just hiding another issue. How can I find the over-release, or the real problem?
If I have fixed the problem, I'd like to know why it's fixed and why I don't need to release the MOC in the second TableViewController
MakeSentenceTableViewController.m
@implementation MakeSentenceTableViewController
@synthesize story, managedObjectContext;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"My Story";
NSLog(@"Passed Story Object: %@", story);
if (managedObjectContext == nil)
{
NSLog(@"managedObjectContext == nil");
managedObjectContext = [(StoryBotAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(@"After managedObjectContext: %@", managedObjectContext);
}else{
NSLog(@"managedObjectContext != nil");
}
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Sentence" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
//sorting stuff:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"order" ascending: YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects: sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
//[request setFetchBatchSize:FETCH_BATCH_SIZE];
[sortDescriptors release];
[sortDescriptor release];
fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:request managedObjectContext:managedObjectContext
sectionNameKeyPath:nil cacheName:nil];
[request release];
NSError *error;
[fetchedResultsController performFetch:&error];
NSLog(@"FetchedResultsController: %@", fetchedResultsController);
NSLog(@"fetchedResultsController RetainCount at viewDidLoad: %d", [fetchedResultsController retainCount]);
}
//snip...table view bits
- (void)dealloc {
[fetchedResultsController release];
//Why don't I have to release this?
//[managedObjectContext release];
[super dealloc];
}