【问题标题】:Releasing CoreData objects with ARC使用 ARC 释放 CoreData 对象
【发布时间】:2013-11-29 20:55:13
【问题描述】:

自从两个月前我搬到 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;
}

在乐器中我使用“僵尸”功能,并看到:

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 代码),但它仍然在“分配摘要”中显示“活着”,所以我不太确定该怎么做。如前所述,这些对象不再使用(或不应该),因此应该全部释放并消失。

【问题讨论】:

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


    【解决方案1】:

    这不是启用僵尸时的默认行为吗?

    启用僵尸检测后,即使保留计数归零,对象也不会被销毁并因此保持活动状态。这是因为僵尸功能专门用于检查过度释放对象的问题。

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

    【讨论】:

    • 哦,是的,这很有道理!今天下午晚些时候我会试试的!我确实注意到使用两个模板得到不同的结果,这确实解释了我认为。我已经有一段时间没有真正使用过乐器了(真丢脸!)随着迁移到 ARC,开启了一个全新的世界。
    猜你喜欢
    • 2012-05-04
    • 1970-01-01
    • 2011-12-18
    • 2014-06-11
    • 1970-01-01
    • 2023-03-19
    • 2013-09-07
    • 2012-10-01
    • 1970-01-01
    相关资源
    最近更新 更多