使用retain获取autorelease对象的所有权?

时间:2012-03-22 14:06:05

标签: objective-c core-data memory-management nsfetchedresultscontroller dealloc

接触以下内容的正确方法是什么? 为了获得具有CoreData对象的列表,我有一个'datamanager',我在其中创建一个NSFetchResultController,进行搜索,并使用对象生成NSFetchResultsController。

因为可以有多个表,所以在每个请求中都需要创建一个新的FetchedResultsController,以便允许自动更新与它们相关联的tableView。

我所做的是在DataManager中创建FetchedResultController,并自动释放它。 在TableViewController中我保留它(假设它将拥有它)。

    NSFetchedResultsController* objects = [[delegate dataManager] getMenu:parentMenu];        
    _objects = [objects retain];

这会调用DataManager:

- (NSFetchedResultsController*) getMenu:(DOMenuItem*) parentMenu {
    NSPredicate* predicate;
    if(parentMenu == nil){
        predicate = [NSPredicate predicateWithFormat:@"(parent == NULL)", parentMenu];
    } else {     
        predicate = [NSPredicate predicateWithFormat:@"(parent == %@)", parentMenu];    
    }

    [NSFetchedResultsController deleteCacheWithName:_cacheName];

    NSFetchedResultsController* aFetchedResultsController = [self createFetchedResultsController];    
    [aFetchedResultsController.fetchRequest setPredicate:predicate];
    [aFetchedResultsController.fetchRequest setFetchLimit:0];

    NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:_defaultSortField ascending:YES] autorelease];
    NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortDescriptor, nil] autorelease];

    [aFetchedResultsController.fetchRequest setSortDescriptors:sortDescriptors];        

    // Fetch the records and handle an error
    NSError *fetchError;

    if (![aFetchedResultsController performFetch:&fetchError]) {
        // Handle the error.
        // This is a serious error and should advise the user to restart the application
        NSLog(@"Fetching data error: %@", [fetchError localizedDescription]);
    }

    return aFetchedResultsController;    
} 

- (NSFetchedResultsController *) createFetchedResultsController {     
    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    NSEntityDescription *entity = [NSEntityDescription entityForName:_objectName inManagedObjectContext:[self managedObjectContext]];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:_defaultSortField ascending:NO] autorelease];
    NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortDescriptor, nil] autorelease];

    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[self managedObjectContext] sectionNameKeyPath:_sectionNameKeyPath cacheName:_cacheName];

    return [aFetchedResultsController autorelease];
} 

但是,我正在运行的情况下,在线路上的调用中,我在此FetchedResultController上收到Dealloc错误。

if(indexPath.section == [[_objects sections] count] + 1){

消息是:

  

* - [NSFetchedResultsController sections]:发送到解除分配的实例0xe3de1b0的消息

这种方法有问题吗? 如果是这样,那么将所有权从创建类“转移”到需要保留它的类的首选方法是什么。

编辑: 当我在返回fetchedResultsController时放置'retain'而不是'autorelease',那么一切正常,但这似乎不适合编码实践,因为'owner'不会释放该对象。我不认为“复制”左右与ManagedObjects一起工作还是这样呢?

1 个答案:

答案 0 :(得分:0)

在非ARC环境中,正确的方法是返回自动释放的对象,然后,如果对象的使用将持续超出接收过程的范围(并且,递归地,调用它的过程,返回对于最接近的自动释放边界),应保留该对象,并提供(通常在"拥有"对象的dealloc方法中)以1对1的方式释放保留。 / p>

请注意,在有条件保留对象的情况下,需要小心 - 不要释放您未保留的内容。