使用ARC释放Core Data对象

时间:2013-11-16 12:27:57

标签: ios objective-c core-data automatic-ref-counting

自从我两个月前搬到ARC以来,我发现我在释放物体时遇到了问题。 我现在正在使用吟唱来试图掌握如何做到这一点,但我有点挣扎。

我有一个计算NSManagedObject的函数。不幸的是,涉及到一些逻辑,所以我实际上需要获取对象(而不是仅仅计数)。

MOC正在主线程上运行,因此用于可见的所有内容。 计数发生在第一个视图(未读标记)上,并且对象本身未在该视图上使用(因此在计数后不再需要)

使用的功能如下:

- (int) getUnreadCount:(DOCategory*) category {
    @autoreleasepool {    
        NSFetchedResultsController* items = [self getUnreadArticlesForCategory:category onlyForCounting:YES];           
        if([[items fetchedObjects] count] == 0) return 0;          
        int counter = 0;
        long commonId = [[[[items fetchedObjects] objectAtIndex:0] commonId] longValue];
        bool read = [[[[items fetchedObjects] objectAtIndex:0] read] boolValue];

        for(DOArticle* article in [items fetchedObjects]){
            long articleCommonId = [article.commonId longValue];
            if(articleCommonId == commonId) {
                //if([article.read boolValue] == true) read = true;
            } else {
                if (!read) {
                    counter++;
                }
                read = [article.read boolValue];
            }

            // If this was the last item, decide if an etra needs to be added
            if([[items fetchedObjects] indexOfObject:article] == [[items fetchedObjects] count] - 1){
                if(!read) {
                    counter++;
                }
            }

            commonId = [[article commonId] longValue];
        }           
        items = nil;          
        return counter;
    }
}

这个函数叫做:

- (NSFetchedResultsController *) getUnreadArticlesForCategory:(DOCategory*) cat onlyForCounting:(bool) onlyForCounting {
    NSPredicate* basePredicate = [NSPredicate predicateWithFormat:@"(((ANY groups.validTime > %@) && (ANY groups.active == YES)) || (ANY groups.universal == YES)) && (site.active == YES) && (removed == NO) && (language.enabled == YES)", [NSDate date]];

    NSPredicate* countPredicate = [NSPredicate predicateWithFormat:@"(ANY categories.countUnread == YES)"];
    NSPredicate* nonCountPredicate = [NSPredicate predicateWithFormat:@"(read == NO)"];

    NSPredicate *predicate = nil;

        NSPredicate* catPredicate = [NSPredicate predicateWithFormat:@"(ANY categories == %@)", cat];
        if (onlyForCounting) {

            predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
                          @[basePredicate, catPredicate, countPredicate]];
        } else {
            predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
                                       @[basePredicate, catPredicate, nonCountPredicate]];
        }

    [NSFetchedResultsController deleteCacheWithName:_cacheName];

    NSFetchedResultsController* aFetchedResultsController = [self createFetchedResultsController:_cacheName sectionString:nil sortBySection:NO];
    [aFetchedResultsController.fetchRequest setPredicate:predicate];
    [aFetchedResultsController.fetchRequest setFetchBatchSize:10];
    [aFetchedResultsController.fetchRequest setFetchLimit:0];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"commonId" ascending:NO];
    NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"language.order" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, sortDescriptor2, nil];

    [aFetchedResultsController.fetchRequest setSortDescriptors:sortDescriptors];

    NSError *fetchError;    
    if (![aFetchedResultsController performFetch:&fetchError]) {
        NSLog(@"Fetching data error: %@", [fetchError localizedDescription]);
    }
    return aFetchedResultsController;
}

在乐器中我使用'Zombies'功能,并看到:

Graph    Category   Live Bytes  # Living    # Transient Overall Bytes   # Overall   Bytes Allocated (Net / Overall)
0   DOArticle_Article_  10.88 KB    174 0   10.88 KB    174 <XRRatioObject: 0x7fe843844f20>  %0.00, %0.00

查看它给出的一个对象:

#   Event Type  ∆ RefCt RefCt   Timestamp   Responsible Library Responsible Caller
0   Malloc  +1  1   00:04.140.423   CoreData    _PFAllocateObject
1   Retain  +1  2   00:04.140.771   CoreData    _faultBatchAtIndex
2   Retain  +1  3   00:04.140.785   iDomsPortalDev  -[DOArticleController getUnreadCount:]
3   Release -1  2   00:04.141.596   iDomsPortalDev  -[DOArticleController getUnreadCount:]
4   Retain  +1  3   00:04.141.599   iDomsPortalDev  -[DOArticleController getUnreadCount:]
5   Release -1  2   00:04.141.614   iDomsPortalDev  -[DOArticleController getUnreadCount:]
6   Release -1  1   00:04.156.411   CoreData    _releaseStaleBatch
7   Release -1  0   00:04.298.640   CoreData    -[_PFArray dealloc]

所以似乎应该释放该对象(因为我输入了@autorelease代码),但它仍然在'Allocations Summary'中说'生活',所以我不太确定该怎么做。如上所述,对象不再使用(或不应该使用),因此应该全部释放并消失。

1 个答案:

答案 0 :(得分:1)

启用Zombies时,这不是默认行为吗?

启用僵尸检测后,即使零售额回零,对象也不会被破坏,因此也会保持活跃状态​​。那是因为僵尸功能特别用于检查过度释放对象的问题。

在其他情况下,我会禁用僵尸检测或仅使用“分配”(或“泄漏”)模板。这将为您提供有关实际内存使用情况,分配(以及生活/瞬态对象)的更准确信息。