无法在dealloc中释放NSFetchedResultsController

时间:2010-10-25 02:50:49

标签: iphone cocoa-touch core-data release-management nsfetchedresultscontroller

我有两个UITableViewControllers,它具有相当简单的ui流程。当您在第一个UITableViewController中选择一个项目时,一个UITableViewController会加载另一个UITableViewController。


(UITableViewController)故事列表 - >选择一个故事 - > (UITableViewController)句子列表


在第二个UITableViewController(MakeSentenceDetailViewController)中,我无法释放我的NSFetchedResultsController而不会导致错误(显示为Zombies设置为on):

  

- [NSFetchRequest release]:发送到解除分配的实例0x5b370f0的消息

NSFetchedResultsController的保留计数保持为1,但是当我尝试在dealloc中释放它时,我遇到了崩溃。

代码,特别是关于NSFetchedResultsController的代码在两个tableviews中是相同的,但是在MakeSentenceDetailViewController中我无法释放这个NSFetchedResults控制器发生崩溃 - 给我一个泄漏。

如何安全地释放我的NSFetchedResultsController?为什么它在父(第一个)tableviewcontroller中工作正常 - 但不在第二个?

我可以为第一个UITableViewController提供代码,但是对于NSFetchedResultsController,它的声明和使用方式大致相同。

MakeSentenceTableViewController.h:

@interface MakeSentenceTableViewController : UITableViewController {
NSManagedObjectContext  *managedObjectContext;  
NSFetchedResultsController *fetchedResultsController;
}
@property (nonatomic, retain)  Story *story;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@end

MakeSentenceTableViewController.m(与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 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];
 }

2 个答案:

答案 0 :(得分:0)

NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
// ...snip...
[request release];

您正在发布一个您已放弃所有权的对象(使用-autorelease)。您不会在另一个版本的位置收到错误,因为NSFetchedResultsController也保留了获取请求;因此,控制器是在释放对提取请求的最后一个引用时实际导致崩溃的控制器。

答案 1 :(得分:0)

你过度释放了NSFetchRequest

你在这里自动发布:

   NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];

然后再次发布:

  [request release];

然后当你释放fetchedResultsController时,它会再次尝试释放同一个请求。