2011-08-20 72 views
0

我非常喜欢使用自定义标题视图和委托方法tableView:viewForHeaderInSection:来获得我想要的外观。但我认为它正在产生内存泄漏,我不知道该怎么做。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]; 
} 

正如你可以看到,每到这个时候被调用时,它实例类型ResultsHeaderView,这是UIView的子类的新对象。

的问题是,它通常被称为,每一个段首标滚动离开视图的,然后再打开,它被称为时间。它会在添加新部分时调用多次,即使对于其他部分也是如此(尽管我可能有一些控制权,但我会研究它)。

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

与此同时,我的理解是创造细胞是昂贵的,这就是为什么他们得到与dequeueReusableCellWithIdentifier过程中重复使用。我必须想象这与节标题是一样的。

会有人谁碰到过这个问题发表评论之前?

回答

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)在上面的代码中都被重置了。

所以,直到我看到一些我错过了,这看起来像它所服务的唯一实例标题视图在需要的时候,和重用那些已经被创建的目的。 (注意,我将autorelease移到了分配视图的位置,我有一个错误,我指的是一个零对象,这个问题解决了这个问题。此外,现在我想起来了,在提到autorelease如果在之前对此代码的调用中实例化了return语句,那么它将多次在对象上重复执行autorelease。我不知道这是否是一个真正的问题,但它很容易拉直了,而我是吧。)

现在,我不删除的部分,所以我不担心关于释放标题视图。但是,如果我做了删除部分,那么就意味着,头视图应该从viewsForSectionHeaders阵列被删除了。

+0

看起来像一个明智的解决方法,我没有尝试过自己的代码,但阅读它我唯一的评论是,似乎有一个假设(可能是一个合理的假设),表视图将总是以正确的顺序请求节标题(即它永远不会在3等之前请求节标题4),如果它曾经要求它们乱序(我不知道它曾经会这样做),我认为你的代码可能会失败。尝试快速滚动表格视图以查看是否可以“跳过”某个部分并查看是否会导致问题。 –

1

遍地可能创建视图是相当昂贵的CPU明智的,虽然我不会想到它会泄露(我从来没有发现泄漏,当我以前使用的技术)。

另一种解决方案(以及我之前使用过的一个解决方案)将创建一个不同类型的自定义单元格,该单元格可以具有不同的单元标识符,并且可以根据需要将它们取出并重新使用 - 然后将其用作头,所以有效行中的每个部分的0您节头和你的真正的行实际上是在第1行中

+0

谢谢,理查德。我已经考虑过这种方法。在这种情况下,我更喜欢使用部分标题。 – Jim

+0

优秀的解决方法。我发现,自定义viewForHeaderInSection可花了我至少5fps的,因为的tableView每次调用它。它很烂。 Apple应该解决这个问题。但在此之前,您的解决方案非常棒。 –

+0

@Jason,谢谢你的积极反馈,这种方法唯一的缺点是,当使用朴素风格时,标题将不会“浮动”在屏幕顶部,直到该部分完全滚动顶部 - 我个人不会不管怎么说,这都是值得一提的。 –