2010-08-23 4 views
32

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

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

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

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

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

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

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

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

+0

Короткий ответ: Да. У него есть отдельная очередь/набор повторного использования, которая не совпадает с вещами, уже встречающимися в таблице. –

ответ

43

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 для использования, после чего вам больше не придется выделять.

+3

Неверная часть «один или два». Он выделял * точно * то, что нужно. Попробуйте, и вы увидите. –

+0

Действительно, как и St3fan, если вы NSLog метод, в котором он запрашивает ячейку, вы увидите, что она запрашивает только ячейку. – Mark

+2

Я, может быть, немного поспешил в том, как я это объяснил. «Что необходимо» варьируется в зависимости от обстоятельств. Когда вы начинаете прокручивать UITableView, в игру вступают больше факторов. Один пример: если вы очень быстро прокручиваете длинный стол, можно заставить таблицу запросить ячейку, если ни один из них не доступен для удаления. –

13

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

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

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

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

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

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

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

2

Целью dequeueReusableCellWithIdentifier является использование меньше памяти. если мы используем 100 ячеек в tableView, тогда вам нужно каждый раз создавать 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; 
} 
Смежные вопросы