UITableView dequeueReusableCellWithIdentifier Теория - PullRequest
33 голосов
/ 24 августа 2010

Когда Apple разработала UITableView для первого iPhone, у них были проблемы с производительностью при прокрутке.Затем один умный инженер обнаружил, что причиной этого было то, что распределение объектов связано с ценой, поэтому он предложил способ повторного использования ячеек.

«Распределение объектов имеет затраты на производительность, особенно еслираспределение должно происходить многократно в течение короткого периода, скажем, когда пользователь прокручивает табличное представление. Если вы повторно используете ячейки вместо выделения новых, вы значительно повышаете производительность табличного представления. "

Источник: Справочная библиотека iOS

Для повторного использования ячейки вы используете:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

Теперь, что мне интересно, что на самом деле происходит здесь?Выглядит ли в TableView, есть ли ячейка с этим идентификатором, и просто возвращает ее?Хорошо, да, но если он отправляет ссылку вместо выделения, и у меня есть табличное представление, скажем, 4 ячейки с одинаковым идентификатором, все они видимы.Как можно умножить себя на четыре экземпляра без выделения?

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

Моя собственная теория заключается в том, что он выделяет четыре ячейки (просто потому, что у них тоже).Когда ячейка исчезнет с экрана, она будет помещена в очередь повторного использования TableView.Когда требуется новая ячейка, она ищет в очереди, доступна ли ячейка с таким же идентификатором, вызывает метод prepareForReuse для этой ячейки и удаляет себя из очереди.

Ответы [ 3 ]

43 голосов
/ 24 августа 2010

dequeueReusableCellWithIdentifier: возвращает cell, только если оно было помечено как готовое к повторному использованию. Вот почему почти в каждом cellForRowAtIndexPath: методе вы увидите что-то вроде



UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (nil == cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                   reuseIdentifier:CellIdentifier];
}

// Do something to cell

return cell;

По сути, будет выделено достаточно строк, чтобы заполнить видимую часть tableview (плюс одну или две дополнительные). Как cells scroll вне экрана, они удаляются из table и помечаются как готовые к reuse. По мере увеличения очереди «доступных ячеек» ваша строка, запрашивающая dequeued cell, начнет получать cell для использования, после чего вам больше не придется выделять.

13 голосов
/ 24 августа 2010

Код для deqeueueReusableCellsWithIdentifier: будет выглядеть примерно так:

(взято из одного из моих собственных проектов, где я делаю нечто подобное с представлениями / страницами в виде прокрутки с постраничной прокруткой)

- (UIView*) dequeueReusablePage
{
    UIView* page = [reusablePages_ anyObject];
    if (page != nil) {
        [[page retain] autorelease];
        [reusablePages_ removeObject: page];
    }
    return page;
}

Таким образом, он сохраняет простой NSMutableSet с объектами многократного использования.

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

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

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

2 голосов
/ 07 сентября 2016

Цель dequeueReusableCellWithIdentifier - использовать меньше памяти. если мы используем 100 ячеек в табличном представлении, то нужно каждый раз создавать 100 ячеек. Это снижает функциональность приложения и может привести к сбою. Для этого dequeueReusableCellWithIdentifier инициализируйте определенное количество ячеек, которые мы создали, и ячейки снова будут использовать для дальнейшей обработки.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *TableIdentifier = @"YourCellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TableIdentifier];
    }

    ExternalClassTableViewCell *myCell = [[ExternalClassTableViewCell alloc]init];
    myCell.MyCellText.text = [tableData objectAtIndex:indexPath.row];
    myCell.MyCellImage.backgroundColor = [UIColor blueColor];

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