Использование iPhone – dequeueReusableCellWithIdentifier

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

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

Вот что обычно делают люди:

 UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"]; // Add elements to the cell return cell; 

И вот как я это сделал:

 // The cell row NSString identifier = [NSString stringWithFormat:@"Cell %d", indexPath.row]; UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (cell != nil) return cell; cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:identifier]; // Add elements to the cell return cell; 

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

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

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

Я не прав, чтобы использовать его таким образом? Или это зависит только от разработчика, в зависимости от его потребностей?

objective dequeueReusableCellWithIdentifier – использовать меньше памяти. Если экран может соответствовать 4 или 5 ячейкам таблицы, то при повторном использовании вам потребуется только 4 или 5 ячеек таблицы, выделенных в памяти, даже если таблица имеет 1000 записей.

Во втором случае повторного использования нет. Во втором случае нет преимущества, поскольку вы используете массив ячеек таблицы. Если ваша таблица имеет 1000 записей, тогда у вас будет 1000 ячеек, выделенных в памяти. Если вы собираетесь сделать это, вы поместите их в массив и просто проиндексируете массив с номером строки и вернете ячейку. Для небольших таблиц с фиксированными ячейками, которые могут быть разумным решением, для динамических или больших таблиц это не очень хорошая идея.

Что касается идентификатора ячейки. Вместо того, чтобы просто использовать «ячейку» для идентификатора, и вместо использования уникального идентификатора, такого как OP, вы могли бы использовать «идентификатор типа»? Например, если в моей таблице было 3 типа ячеек: один с очень сложным Style1 , один с одним Style2 и один с Style2 , я должен был идентифицировать эти три отдельно, а затем просто перестроить их, если dequeue окажется nil .

Например:

 -(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{ NSString* ident = @""; if(indexPath.section == 0) ident= @"complicated"; if(indexPath.section == 1) ident= @"style1"; if(indexPath.section == 2) ident = @"style2"; UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:ident]; if(cell == nil){ if(ident == @"complicated"){ cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:ident] autorelease]; // do excessive subview building } if(ident == @"style1"){ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyle1 reuseIdentifier:ident] autorelease]; } if(ident == @"style2"){ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyle2 reuseIdentifier:ident] autorelease]; } } if(ident == @"complicated"){ // change the text/etc (unique values) of our many subviews } if(ident == @"style1"){ [[cell textLabel] setText:@"Whatever"]; } if(ident == @"style2"){ [[cell textLabel] setText:@"Whateverelse"]; } return cell; } 

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

Я не думаю, что Apple создала бы идею многократного использования ячейки с идентификаторами, если бы они хотели, чтобы все идентификаторы были "cell" , не так ли?

Документация, которая помогла мне понять, почему идиоматический способ (тот, который вы описали вначале) лучше всего работает, – это ссылочный раздел classа UITableViewCell в методе initWithStyle:reuseIdentifier: .

Подраздел reuseIdentifier читает:

Вы должны использовать один и тот же идентификатор повторного использования для всех ячеек той же формы.

В подразделе «Обсуждение» говорится:

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

Эти утверждения дают мне понять, что идиоматический способ использования dequeueReusableCellWithIdentifier внутри вашей реализации tableView:cellForRowAtIndexPath: для вашего UITableViewDataSource создается один объект ячейки для каждой видимой строки независимо от общего количества доступных строк.

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

UITableView внутренне использует ячейку с идентификатором как «Шаблон». Таким образом, в следующий раз, когда вы (прочитайте как таблицу) попробуйте deque, он просто создает новую ячейку, но использует хранимый объект в качестве шаблона. Следовательно, вам все равно придется обновлять свой пользовательский интерфейс, чтобы отразить содержимое ячейки в контексте.

Это также означает, что UITableView делает управление памятью для ячеек для нас сам по себе. Теоретически, будет только так много объектов UITableViewCell сколько видимых ячеек. Но практически, может быть еще пара ожидающих освобождения памяти.

Это в основном экономит память большого времени, особенно в сценариях, где у вас 1000 ячеек.

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

С другой стороны, если ваша ячейка является настроенной ячейкой, мы можем, скорее всего, загрузить с нее нить и извлечь ее. Если это так, вы можете использовать идентификатор для deque ИЛИ, вы можете загрузить его из nib. Нет никакой разницы в процедуре.

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

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

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

UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath]

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

  • Использование индекса, используя временный, с помощью filesort - как это исправить?
  • Что такое Haskell's Stream Fusion
  • Какова механика оптимизации коротких строк в libc ++?
  • Перемещает бит быстрее, чем умножение и деление на Java? .СЕТЬ?
  • Должны ли операции импорта всегда находиться в верхней части модуля?
  • Каков наилучший способ установить регистр в ноль в сборке x86: xor, mov или или?
  • Готово ли java final помочь компилятору создать более эффективный байт-код?
  • Почему пустая оптимизация базового classа не работает?
  • Проверьте, равен ли регистр нулю с помощью CMP reg, 0 против OR reg, reg?
  • Могут ли компиляторы исключать бесконечные петли?
  • Округление до следующей мощности 2
  • Давайте будем гением компьютера.