viewForHeaderInSection创建内存泄漏?

时间:2011-08-20 15:10:39

标签: objective-c uitableview custom-controls sectionheader

我使用自定义标题视图和委托方法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];
}

正如您所看到的,每次调用它时,它都会实例化一个ResultHeaderView类型的新对象,它是UIView的子类。

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

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

与此同时,我的理解是创建单元格成本很高,这就是为什么它们会被dequeueReusableCellWithIdentifier进程重用。我必须想象这与节标题相同。

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

2 个答案:

答案 0 :(得分: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时,它可能会将先前关联的标题与其最初匹配的不同部分“不匹配”。但这并不重要,因为标题属性(text,searchTermsEntity,resultDelegate和section)都在上面的代码中重置。

因此,在我看到错过的内容之前,看起来它只是为了在需要时实例化标题视图,并重用那些已经创建的标题视图。

(请注意,我在自动释放内部移动了视图的位置。我有一个错误,我指的是一个nil对象,这就修复了它。而且,现在我想到了它,在返回时讨论自动释放如果在上一次调用此代码时已经实例化了语句,那么语句会多次重复对象的自动释放。我不知道这是否是一个真正的问题,但是当我在它的时候很容易理顺它。)

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

答案 1 :(得分:1)

反复创建视图可能是非常昂贵的CPU,虽然我不会想到它会泄漏(我之前从未注意到泄漏时使用该技术)。

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

相关问题