обязательно ли dequeueReusableCellWithIdentifier, чтобы избежать утечек памяти? - PullRequest
0 голосов
/ 07 марта 2012

Я использую «знаменитый» шаблонный код, который почти каждый использует для обработки cellForRowAtIndexPath:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"someCustomCellID"];  
if (cell == nil)  // nothing to recycle from the queue: create a new cell

, но это доставляет мне много проблем, потому что мои ячейки содержат изображения, которые я загружаю асинхронно, и две функции (снятие очереди и асинхронная загрузка) часто конфликтуют.Поэтому я стараюсь каждый раз создавать новую ячейку, и она работает довольно хорошо и быстро.Но у меня есть сомнения: должен ли я вызывать dequeueReusableCellWithIdentifier, чтобы освободить память, даже если я игнорирую возвращаемое значение и создаю ячейки каждый раз?Я предполагаю, что ячейки, которые больше не используются, автоматически освобождаются (как и должно быть), но мне интересно, может ли очередь кэширования потребовать явного освобождения при вызове dequeue ...

Ответы [ 5 ]

4 голосов
/ 07 марта 2012

dequeueReusableCellWithIdentifier не предназначен для предотвращения утечек памяти, но предназначен для повышения производительности (одним из способов является снижение использования памяти).При использовании метода dequeue прокрутка табличного представления будет намного более плавной, если имеется несколько строк данных.Я бы порекомендовал вам использовать асинхронную загрузку для работы с методом dequeue, особенно если вы видите какие-либо задержки при прокрутке.Если вам нужен пример того, как это сделать, см. Пример Apple LaxyTableImages .Однако если вы решите, что не хотите повторно использовать ячейки, просто передайте nil как reuseIdentifier при создании своих ячеек.

2 голосов
/ 07 марта 2012

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

2 голосов
/ 07 марта 2012

dequeueReusableCellWithIdentifier помогает сократить количество загрузок и перезагрузки файлов из файлов или XIB. Если у вас есть пользовательская ячейка или ячейки с нестандартным содержимым, повторное использование ячейки, в которой она уже настроена, может быть намного быстрее.

Я помню, что работал над чем-то похожим, но в нашем случае мы загружали изображения в объекты Core Data асинхронно и позволяли ячейке наблюдать изображение в этом объекте. Когда изображение было загружено, ячейка была уведомлена, и она обновила свой вид изображения.

Когда ячейка вернулась к нам через dequeueReusableCellWithIdentifier, мы остановили ее наблюдение и установили для наблюдения изображения следующего объекта.

0 голосов
/ 07 марта 2012

Вы должны использовать метод, всегда.Если он возвращает ячейку, используйте эту ячейку.Если он возвращает nil, тогда и только тогда вы должны создать ячейку.

Если метод требует ячейку для изображения, которое вы еще не загрузили, вам следует предоставить альтернативу.Возможно UIImageView с настроенным, анимированным счетчиком прогресса?Затем, когда ваше изображение прибудет, вы можете использовать подходящее изображение, когда это необходимо.

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

0 голосов
/ 07 марта 2012

Да, вам нужно использовать dequeueReusableCellWithIdentifier, чтобы избежать утечек, если вы динамически распределяете ячейки.

Предположительно, ваша асинхронная загрузка изображений работает примерно так:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (!cell) {
        ...
    }

    NSURLRequest *request = [self URLRequestForIndexPath:indexPath];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            cell.imageView.image = [UIImage imageWithData:data];
        }];

    return cell;
}

У этого кода есть проблема. К моменту запуска обработчика завершения в табличном представлении ячейка может использоваться для другой строки!

Нам нужно изменить блок завершения, чтобы он просматривал ячейку для строки, когда он готов установить изображение:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (!cell) {
        ...
    }

    NSURLRequest *request = [self URLRequestForIndexPath:indexPath];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            if (cell)
                cell.imageView.image = [UIImage imageWithData:data];
        }];

    return cell;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...