2016-08-29 2 views
4

Я знаю, что этот вопрос немой. Но неожиданно застрял в этом вопросе.Должен ли я использовать dequeReusableCellWithIdentifier?

Когда я использую dequeReusableCellWithIdentifier, ячейки повторно используются. Более конкретно, сначала 'n' набор ячеек повторно используется вместе с их .

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

Предположим, что я использую пользовательский комплекс UITableviewcell. (Я знаю, что мы должны уменьшить сложность, но все же ...)

Некоторые элементы должны быть добавлены в ячейку.

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

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

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

Я думал использовать DrawRect метод, но он не работает с UITableViewAutomaticDimension

Если я не использую dequeReusableCell, я буду иметь индивидуальные ссылки клетки, но это будет стоить память и производительность.

Итак, что является лучшим решением? Могу ли я использовать dequeReusableCell и все еще не нужно переписывать его содержимое?

Редактировать 1: Упомянув dequeReusableCell, я упомянул dequeueReusableCellWithIdentifier - forIndexPath. Прошу прощения за путаницу.

Edit 2: Я чувствую, что я не так ясно в моем вопросе.

Давайте рассмотрим, что у меня есть массив в моем контроллере view. Я конфигурирование своей ячейки в cellForRowAtIndexPath с dequeueReusableCellWithIdentifier - forIndexPath

Так что же происходит, каждый раз я прокрутку, когда невидимые строки становятся видимыми, cellForRowAtIndexPath называются.

Скажем, у меня есть слайдер изображения с n изображениями. Для каждой ячейки это «n» отличается. Поэтому я вынужден рисовать представление ячейки на основе своего источника данных.

Таким образом, каждый раз, когда tableView вызывает cellForRowAtIndexPath, ячейка настроена снова и снова.

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

+0

Не сохраняйте ссылки. Каждый раз, когда вам нужна ссылка на * visible * cell в 'indexPath' - вызов' if let cell = tableView.cellForRowAtIndexPath (indexPath) {} ' –

+0

Надеюсь, что cellForRowAtIndexPath больше не будет возвращать нуль. Так что эта проверка бесполезна. Исправьте меня, если неправильно –

+0

'cellForRowAtIndexPath (_ :)' return 'nil', если ячейка в' indexPath' не отображается или 'indexPath' находится за пределами допустимого диапазона. –

ответ

1

что я делаю в этом случае заключается в следующем:

  1. Я всегда использую dequeReusableCell:, по причинам, вы уже сказали
  2. Я пишу метод cleanCell в пользовательском UITableViewCell классе для того, чтобы очистить все имеет был уже установлен на ячейку (только чтобы он был готов к повторному использованию)
  3. затем в cellForRowAtIndexPath: настроить свою камеру по желанию
+0

Да, я делаю уборку в методе prepareForReuse. Я просто спрашиваю, есть ли способ поддерживать источник данных соты. –

+0

@ Shob-Z, что вы имеете в виду под "* maintain *"? – ddb

+0

Хорошо. Например, у меня есть переменная myData для пользовательского UITableviewcell. Теперь я установил это значение myData для конкретной ячейки в pathpath. Я установил другое значение для другой ячейки в другом указателе. Когда ячейки повторно используются, myData второй ячейки вернет myData первой ячейки. Это заставляет нас устанавливать переменную каждый раз, когда мы вызываем cellForRowAtIndexPath. Мы не можем поддерживать ценность! Я не уверен, насколько я достаточно ясен. –

0

В вашем случае вы должны использовать метод dequeueReusableCellWithIdentifier(_ identifier: String, forIndexPath indexPath: NSIndexPath). Этот метод автоматически определяет, нужно ли создавать или отменять ячейку.

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

Вам не нужно добавлять эти представления при каждом вызове cellForRowAtIndexPath. Эти представления должны быть уже добавлены по мере создания экземпляра ячейки. В cellForRowAtIndexPath вы только присваиваете изображения и другие значения этим представлениям.

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

var items = [UIImage]() 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCellWithIdentifier("ImageCell", forIndexPath: indexPath) 

    let item = items[indexPath.row] 
    let recipient = item.recipients.first 

    // I have given my UIImageView tag = 101 to easily access it from the view controller. 
    // This allows me to avoid defining a custom UITableViewCell subclass for simple cells. 
    if let imageView = cell.viewWithTag(101) as? UIImageView { 
     imageView.image = item 
    } 

    return cell 
} 
+0

1. Да, я использую dequeueReusableCellWithIdentifier (_ identifier: String, forIndexPath indexPath: NSIndexPath) 2. Представьте, что у вас n число imageviews. Это «n» отличается для каждой ячейки. Поэтому я не могу исправить определенное количество просмотров во время создания ячейки. Мне нужно как создавать представления, так и назначать изображения в cellForRowAtIndexPath –

+0

@ Теперь Shob-Z получил вашу проблему. В этом случае, вероятно, лучше иметь еще один «UITableView» внутри ячейки. –

+0

Я пытаюсь уменьшить нагрузку! Добавление другого вида tableview/collectionview увеличит его. –

1

Вот что я хотел бы сделать: Я хотел бы переместить логику добавления этих тяжелых взгляды внутри самого класса клетки. Так что в cellForRowAtIndexPath я бы просто установил объект, который должен отображаться внутри ячейки, и ячейка сама создала бы все необходимые виды (в конце концов, это слой вида). Так что внутри cellForRowAtIndexPath это будет выглядеть примерно так:

cell = [tableView dequeueReusableCellWithIdentifier...forIndexPath...]; 
cell.modelObject = myModelObject; 

и это все.

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

Если честно, я не получаю ваш пример с помощью слайдера, но давайте предположим, что у вас есть звездный рейтинг с 5 звездами, который может быть видимым или нет. Есть несколько способов сделать это, но предположим, что вы просто добавляете/удаляете UIImageView для каждой звезды. Как вы это делаете сейчас, у вас будет пустая ячейка и создание/добавление просмотров в cellForRow. Я предлагаю иметь 5 UIImageView s как часть вашей ячейки, а внутри ячейки установить их видимость на основе modelObject.rating. Что-то вроде того. Надеюсь, это поможет проиллюстрировать мою точку :)

UPDATE: когда ваша ячейка может иметь в себе суровое количество изображений, я бы, вероятно, создал их внутри класса ячейки. Так, например, для первого объекта модели нам нужны 3 изображения. Поэтому мы их создаем. Но тогда мы не выпускаем их в prepareForReuse, мы ждем следующего объекта модели. И если у него есть, скажем, 1 изображение, мы выпускаем 2 изображения (или нет, поэтому нам не нужно было их позже создавать, это зависит от того, что является более критичным: производительность или использование памяти) и если ему нужно 5, мы создаем еще два. И если ему нужно 3, мы все уже настроены.

+0

Это лучший альтернативный вариант. Я это рассмотрю. –

0

1) Я думаю, вам нужно использовать «ленивую нагрузку» на ячейки. http://www.theappguruz.com/blog/ios-lazy-loading-images (например)

2) Вы можете создать свойство в вашем ViewController и создать NSMutableDictionary свойство, которое будет хранить некоторые данные в какой-то ключ, если ваша модель имеет такие вещи, как «ID» из или вы можете использовать indexPath.row для него, тогда вы можете загрузить его только один раз, и в следующий раз, когда будет вызван -cellForRow, вы можете получить данные из своего словаря с помощью

[self.dataDictionary objectForKey: @ "CellID"];

И с этим вы решите свою повторяющуюся нагрузку. In-cellForRow вы можете установить чек, например.

if ([self.dataDictionary objectForKey:@"cellID"]) { 
    cell.cellImage = [self.dataDictionary objectForKey:@"cellID"]; 
} else { 
    UIImage *img = [uiimage load_image]; 
    cell.cellImage = img; 
    [self.dataDictionary setObject:img forKey:@"cellID"]; 
} 

И так далее. Пример, например, тип dataType, который вы можете выбрать самостоятельно, это пример.

0

Спасибо, что помогли мне всем. Я думаю, лучший ответ был от @Eiko.

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

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

Смежные вопросы