0

我使用自定义标题视图和委托方法 tableView:viewForHeaderInSection: 获得了我想要的外观非常成功。但我认为它正在产生内存泄漏,我不知道该怎么办。

代码是这样的:

- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    NSLog (@"New header, section %d", section);
    ResultsHeaderView *header = [[ResultsHeaderView alloc] initWithFrame:CGRectMake(0, 0, defaultResultsHeaderSize.width, defaultResultsHeaderSize.height)];

    SearchResult *result = [[[[self.fetchedResultsController sections] objectAtIndex:section] objects] objectAtIndex:0];

    header.text = result.searchUsed.keywords;
    header.searchTermsEntity = result.searchUsed;
    header.resultDelegate = self;
    header.section = section;

    return [header autorelease];
}

可以看到,每次调用this时,都会实例化一个ResultHeaderView类型的新对象,它是UIView的子类。

问题是它经常被调用,每次一个节标题从视图中滚动出来然后又重新打开时,它就会被调用。添加新部分时,它会被多次调用,即使对于其他部分也是如此(尽管我可能对此有一些控制,我将对其进行研究。)

我想知道是否有类似 tableView:dequeueReusableCellWithIdentifier: 可以管理节标题视图,或者知道何时需要发布节标题视图的方法。我不确定自动释放是否足以避免泄漏。

同时,我的理解是创建单元格的成本很高,这就是为什么它们可以通过 dequeueReusableCellWithIdentifier 过程重用。我不得不想象这与节标题相同。

有谁在评论之前遇到过这个问题吗?

4

2 回答 2

2

这就是我决定要做的事情,除非有人能看出其中的缺陷或能想出一个更好的主意。

在管理 tableView 的视图控制器中,我添加了一个属性

NSMutableArray *viewsForSectionHeaders;

然后我修改了我的 tableView:viewForHeaderInSection:

- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    SearchResult *result = [[[[self.fetchedResultsController sections] objectAtIndex:section] objects] objectAtIndex:0];

    ResultsHeaderView *header;

    if (section < [viewsForSectionHeaders count]) {
        header = [viewsForSectionHeaders objectAtIndex:section];
    }
    else {
        header = [[[ResultsHeaderView alloc] initWithFrame:CGRectMake(0, 0, defaultResultsHeaderSize.width, defaultResultsHeaderSize.height)] autorelease];
        [viewsForSectionHeaders addObject:header];
    }

    header.text = result.searchUsed.keywords;
    header.searchTermsEntity = result.searchUsed;
    header.resultDelegate = self;
    header.section = section;

    return header;
}

在这种情况下,我有一组标题视图。这不是很明显,但是每当更新 fetchedResultsController 时,它可能会“不匹配”先前关联的标头与它们最初匹配的部分不同。但这并不重要,因为标题属性(文本、searchTermsEntity、resultDelegate 和部分)都在上面的代码中重置。

所以,在我看到我错过的东西之前,这看起来只是为了在需要时实例化标题视图,并重用那些已经创建的视图。

(请注意,我将 autorelease 移到了分配视图的位置。我在引用 nil 对象时遇到了一个错误,这修复了它。另外,现在我想到了,在 return 语句中使用 autorelease 会有如果在之前对该代码的调用中实例化了一个对象,则多次重复该对象的自动释放。我不知道这是否是一个真正的问题,但当我在处理它时,很容易解决这个问题。)

现在,我不删除部分,所以我不必担心释放标题视图。但是如果我确实删除了部分,那么这意味着标题视图也应该从 viewsForSectionHeaders 数组中删除。

于 2011-08-20T17:44:06.870 回答
1

一遍又一遍地创建视图在 CPU 方面可能是相当昂贵的,尽管我不会想到它会泄漏(我以前使用过这种技术时从未注意到泄漏)。

另一种解决方案(我以前自己使用过的解决方案)是创建一种不同类型的自定义单元格,它可以具有不同的单元格标识符,并且可以根据需要出列和重用 - 然后将其用作标题,所以行每个部分的 0 实际上是您的部分标题,而您的真正行实际上从第 1 行开始。

于 2011-08-20T15:16:23.513 回答