viewForHeaderInSection создает утечку памяти? - PullRequest
0 голосов
/ 20 августа 2011

Я получаю большой успех, получая нужный мне вид, используя пользовательский вид заголовка и метод делегата 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];
}

Как видите, каждый раз, когда он вызывается, он создает новый объект типа ResultsHeaderView, который является подклассом UIView.

Проблема в том, что он вызывается часто, каждый раз, когда заголовок раздела прокручивается вне представления и затем снова включается, он вызывается. Он вызывается несколько раз при добавлении нового раздела, даже для других разделов (хотя я могу иметь некоторый контроль над этим, и я собираюсь изучить его.)

Мне интересно, есть ли что-то вроде tableView: dequeueReusableCellWithIdentifier: которое может управлять представлениями заголовка раздела или способом узнать, когда представление заголовка раздела нуждается в выпуске. Я не уверен, достаточно ли автоматического выпуска, чтобы избежать утечки.

В то же время я понимаю, что создание ячеек является дорогостоящим, и поэтому они повторно используются в процессе dequeueReusableCellWithIdentifier. Я должен представить, что это будет то же самое с заголовками разделов.

Будет ли кто-нибудь, кто сталкивался с этой проблемой до комментария?

Ответы [ 2 ]

2 голосов
/ 20 августа 2011

Вот то, что я решил сделать, если кто-то не видит в нем недостаток или не может придумать лучшую идею.

В контроллере представления, который управляет 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) сбрасываются в приведенном выше коде.

Итак, до тех пор, пока я не увижу что-то, что пропустил, похоже, что он служит только для создания экземпляров представлений заголовков, когда они необходимы, и повторного использования тех, которые уже были созданы.

(Обратите внимание, что я переместил авторелиз внутри, где размещено представление. У меня была ошибка, когда я ссылался на нулевой объект, и это исправило его. Кроме того, теперь, когда я думаю об этом, произойдет авторелиз в возврате оператор повторил бы авторелиз на объекте несколько раз, если бы он был создан при предыдущем обращении к этому коду. Я не знаю, является ли это реальной проблемой, но это было легко исправить, пока я занимался этим .)

Прямо сейчас я не удаляю разделы, поэтому мне не нужно беспокоиться об освобождении представлений заголовков. Но если я действительно удаляю разделы, это означает, что представление заголовка должно быть удалено и из массива viewsForSectionHeaders.

1 голос
/ 20 августа 2011

Создание представления снова и снова, вероятно, довольно дорого с точки зрения процессора, хотя я бы не подумал, что оно будет утечкой (я никогда не замечал утечки, когда использовал эту технику раньше).

Anальтернативное решение (и одно, которое я ранее использовал сам) состояло бы в создании другого типа пользовательской ячейки, которая может иметь другой идентификатор ячейки и которая может быть удалена и повторно использована по мере необходимости - и затем использовать это в качестве заголовка, поэтому строка 0каждого раздела, по сути, ваш заголовок раздела и ваши подлинные строки на самом деле начинаются с 1-й строки.

...