为什么我不必在第二个TableViewController中发布managedObjectContext

时间:2010-10-26 23:07:19

标签: iphone cocoa-touch core-data memory-leaks release-management

我有两个显示CoreData对象的tableview控制器。一个是详细视图(带有句子),一个是概述(带有故事)。 选择一个故事 - >看句子。

看起来我过度释放了我的managedObjectContext;我最初在dealloc的两个TableViewControllers中都发布了它,并且我每三次在两个控制器之间发生崩溃(故事 - >句子 - >故事 - >句子 - >故事 - >崩溃)。 一些调试显示我在两个TableViewControllers的ViewDidLoad中的代码后,我的App Delegate崩溃了:

 if (managedObjectContext == nil) 
{ 
    managedObjectContext = [(StoryBotAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
    NSLog(@"After managedObjectContext: %@",  managedObjectContext);
}

更多研究发现this discussion让我相信这是一个过度发布的ManagedObjectContext案例:

  

第二个更平淡无奇的问题只是过度释放   NSManagedObject。仪器ObjectAlloc工具应该能够提供帮助   你。

所以我删除了[managedObjectContext release];来自我在TableViewController中的dealloc,现在我没有泄漏(根据Instruments)并且没有崩溃。

看起来问题已解决,但问题是:

  • 我可能完全忽略了这一点,只是隐藏了另一个问题。如何找到过度释放或真正的问题?

  • 如果我已经修复了问题,我想知道为什么它已修复,为什么我不需要在第二个TableViewController中释放MOC

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];
}

1 个答案:

答案 0 :(得分:6)

因为你没有保留它。即使您查看控制器中的“MOC”属性是(保留),您也不会调用setter,而只是直接设置引用。如果要保留并释放它,则必须调用 self.managedObjectContext = ... (注意点),这相当于 [self setManagedObjectContext:...] < / em>然后才能在dealloc中安全地释放它。实际上,由于“MOC”由应用代表拥有和管理,我甚至懒得保留它。