Can't Release NSFetchedResultsController in dealloc
I have two UITableViewControllers with a fairly simple ui flow. One UITableViewController loads another UITableViewController when you select an item in the first UITableViewController.
(UITableViewController) List of Stories -> Select a Story -> (UITableViewController) List of Sentences
In the second UITableViewController (MakeSentenceDetailViewController) I can't release my NSFetchedResultsController without causing an error (shown with Zombies set to on):
-[NSFetchRequest release]: message sent to deallocated instance 0x5b370f0
The retain count of the NSFetchedResultsController stays at 1 but when I try to release it in dealloc I get a crash.
The code, especially in regards to the NSFetchedResultsController is the same in both tableviews, but in the MakeSentenceDetailViewController I can't release this NSFetchedResults Controller with a crash - giving me a leak.
How can I safely release my NSFetchedResultsController? Why does it work fine in the parent (first) tableviewcontroller - but not in the second?
I can provide code for the first UITableViewController but in regards to NSFetchedResultsController it's declared and used in much the same way.
MakeSentenceTableViewController.h:
@interface MakeSentenceTableViewController : UITableViewController {
NSManagedObjectContext *managedObjectContext;
NSFetchedResultsController *fetchedResultsController;
}
@property (nonatomic, retain) Story *story;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@end
MakeSentenceTableViewController.m (relevant code with NSFetchedResultsController):
- (void)viewDidLoad {
[super viewDidLoad];
if (managedObjectContext == nil)
{
managedObjectContext = [(MyAppAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(@"After managedObjectContext: %@", managedObjectContext);
}
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
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 开发者_JAVA百科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]);
}
- (void)dealloc {
//Gotta figure out why I can't release this:
[fetchedResultsController release]; //Crash! Burn!
NSLog(@"fetchedResultsController RetainCount at dealloc: %d", [fetchedResultsController retainCount]);
[managedObjectContext release];
[super dealloc];
}
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
// ...snip...
[request release];
You're releasing an object that you've relinquished ownership of (with -autorelease
). You don't get an error at the point of the other release because the NSFetchedResultsController is also retaining the fetch request; thus the controller is the one actually causing the crash when it releases the last reference to the fetch request.
You are over-releasing the NSFetchRequest
You autorelease it here:
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
then release it again later:
[request release];
then later when you release the fetchedResultsController, it tries to release that same request again.
精彩评论