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];
}

ご覧のとおり、これが呼び出されるたびに、UIViewのサブクラスであるResultsHeaderViewタイプの新しいオブジェクトがインスタンス化されます。

問題は、それが頻繁に呼び出されることです。セクションヘッダーがビューからスクロールアウトされてから再びオンになるたびに、呼び出されます。新しいセクションが追加されると、他のセクションであっても、何度も呼び出されます(ただし、それをある程度制御できる可能性があるので、これを調べます)。

tableView:dequeueReusableCellWithIdentifier:のように、セクションヘッダービューを管理できるものや、セクションヘッダービューにリリースが必要な時期を知る方法があるかどうか疑問に思っています。自動リリースがリークを回避するのに十分かどうかはわかりません。

同時に、セルの作成にはコストがかかることを理解しています。そのため、セルはdequeueReusableCellWithIdentifierプロセスで再利用されます。これはセクションヘッダーでも同じだと想像する必要があります。

コメントする前にこの問題に遭遇した人はいますか?

4

2 に答える 2

2

誰かがそれに欠陥を見ることができるか、より良いアイデアを思い付くことができない限り、これが私がすることに決めたものです。

tableViewを管理するViewControllerに、プロパティを追加しました

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オブジェクトを参照しているときにエラーが発生し、これで修正されました。また、考えてみると、returnステートメントの自動リリースには次のようになります。このコードへの以前の呼び出しでインスタンス化されていた場合、オブジェクトの自動解放を複数回繰り返しました。それが本当の問題であるかどうかはわかりませんが、それを修正するのは簡単でした。)

今のところ、セクションを削除しないので、ヘッダービューを解放することを心配する必要はありません。ただし、セクションを削除した場合は、viewsForSectionHeaders配列からヘッダービューも削除する必要があることを意味します。

于 2011-08-20T17:44:06.870 に答える
1

ビューを何度も作成することは、CPUに関してはかなり高価ですが、リークするとは思わなかったでしょう(以前にその手法を使用したときにリークに気づいたことはありません)。

別の解決策(および私が以前に自分で使用したもの)は、異なるセルIDを持つことができ、必要に応じてデキューして再利用できる異なるタイプのカスタムセルを作成し、これをヘッダーとして使用することです。各セクションの0は事実上セクションヘッダーであり、実際の行は実際には行1から始まります。

于 2011-08-20T15:16:23.513 に答える