Загрузка повторно используемой UITableViewCell из кончика
-
03-07-2019 - |
Вопрос
Я могу создавать пользовательские UITableViewCells и загружать их просто отлично, используя технику, описанную в теме, найденной по адресу http://forums.macrumors.com/showthread.php?t=545061.Однако использование этого метода больше не позволяет вам инициализировать ячейку с помощью reuseIdentifier, что означает, что вам нужно создавать совершенно новые экземпляры каждой ячейки при каждом вызове.Кто-нибудь придумал хороший способ по-прежнему кэшировать определенные типы ячеек для повторного использования, но при этом иметь возможность создавать их в Interface Builder?
Решение
Просто реализуйте метод с соответствующей сигнатурой метода:
- (NSString *) reuseIdentifier {
return @"myIdentifier";
}
Другие советы
На самом деле, поскольку вы создаете ячейку в Интерфейсном Разработчике, просто установите там идентификатор повторного использования:
Или, если вы работаете в Xcode 4, проверьте вкладку «Инспектор атрибутов»:
(Правка: после того, как XIB сгенерирован вашим XIB, он содержит пустой UIView, но нам нужен UITableViewCell; поэтому вам нужно вручную удалить UIView и вставить ячейку табличного представления. Конечно, IB не будет показывать никакой UITableViewCell параметры для UIView.)
Теперь в iOS 5 есть соответствующий метод UITableView для этого:
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
Я не могу вспомнить, где я первоначально нашел этот код, но до сих пор он отлично работал для меня.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"CustomTableCell";
static NSString *CellNib = @"CustomTableCellView";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (UITableViewCell *)[nib objectAtIndex:0];
}
// perform additional custom work...
return cell;
}
<Ч>
Пример настройки Interface Builder ...
Посмотрите на ответ, который я дал на этот вопрос:
Возможно ли создавать подклассы NSCell в интерфейсе Builder?
Не только возможно спроектировать UITableViewCell в IB, это желательно, потому что в противном случае все ручное подключение и размещение нескольких элементов очень утомительно. Производительность хороша, если вы по возможности стараетесь сделать все элементы непрозрачными. ReuseID устанавливается в IB для свойств UITableViewCell, затем вы используете соответствующий код повторного использования в коде при попытке удаления из очереди.
В прошлом году я также слышал от некоторых докладчиков на WWDC, что в IB не следует создавать ячейки табличного представления, но это большая нагрузка. Р>
Начиная с iOS 4.0, в документации для iOS есть специальные инструкции, которые делают эту работу очень быстрой:
Прокрутите вниз, где говорится о создании подкласса UITableViewCell.
Вот еще один вариант:
NSString * cellId = @"reuseCell";
//...
NSArray * nibObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomTableCell" owner:nil options:nil];
for (id obj in nibObjects)
{
if ([obj isKindOfClass:[CustomTableCell class]])
{
cell = obj;
[cell setValue:cellId forKey:@"reuseIdentifier"];
break;
}
}
Я создаю свои пользовательские ячейки просмотра аналогичным образом, за исключением того, что я подключаю ячейку через IBOutlet.
Тот Самый [nib objectAt...]
подход чувствителен к изменениям положения элементов в массиве.
Тот Самый UIViewController
подход хорош - просто попробовал его, и он работает достаточно хорошо.
НО...
Во всех случаях initWithStyle
конструктор НЕ вызывается, поэтому инициализация по умолчанию не выполняется.
Я читал различные места об использовании initWithCoder
или awakeFromNib
, но нет убедительных доказательств того, что любой из этих способов является правильным.
Помимо явного вызова некоторого метода инициализации в cellForRowAtIndexPath
метод Я пока не нашел ответа на этот вопрос.
Некоторое время назад я нашел отличную запись в блоге на эту тему по адресу blog.atebits.com и с тех пор начал использовать класс ABTableViewCell Лорен Бричтер для выполнения всех моих UITableViewCells.
В итоге вы получаете простой контейнер UIView для размещения всех ваших виджетов, а прокрутка молниеносна.
Надеюсь, это полезно.
Этот метод также работает, и для управления памятью в вашем контроллере представления не требуется прикольный ivar. Здесь ячейка пользовательского табличного представления находится в XIB с именем " CustomCell.xib ".
static NSData *sLoadedCustomCell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
if (cell == nil)
{
if (sLoadedCustomCell == nil)
{
// Load the custom table cell xib
// and extract a reference to the cell object returned
// and cache it in a static to avoid reloading the nib again.
for (id loadedObject in [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:nil options:nil])
{
if ([loadedObject isKindOfClass:[UITableViewCell class]])
{
sLoadedCustomCell = [[NSKeyedArchiver archivedDataWithRootObject: loadedObject] retain];
break;
}
}
cell = (UITableViewCell *)[NSKeyedUnarchiver unarchiveObjectWithData: sLoadedCustomCell];
}
Метод Луи работал на меня. Вот код, который я использую для создания UITableViewCell из пера:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"CustomCellId"];
if (cell == nil)
{
UIViewController *c = [[UIViewController alloc] initWithNibName:@"CustomCell" bundle:nil];
cell = (PostCell *)c.view;
[c release];
}
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
return cell;
}
Решение gustavogb не работает для меня, я попробовал следующее:
ChainesController *c = [[ChainesController alloc] initWithNibName:@"ChainesController" bundle:nil];
[[NSBundle mainBundle] loadNibNamed:@"ChaineArticleCell" owner:c options:nil];
cell = [c.blogTableViewCell retain];
[c release];
Кажется, это работает. BlogTableViewCell является IBOutlet для ячейки, а ChainesController является владельцем файла.
Из документов UITableView относительно dequeueWithReuseIdentifier
: " строка, идентифицирующая объект ячейки для повторного использования. По умолчанию идентификатором повторно используемой ячейки является имя класса, но вы можете изменить его на любое произвольное значение. & Quot;
Переопределять -reuseIdentifer самостоятельно рискованно. Что произойдет, если у вас есть два подкласса вашего подкласса ячеек, и вы используете оба в одном табличном представлении? Если они отправят вызов идентификатора повторного использования на super, вы удалите из очереди ячейку неправильного типа .............. Я думаю, вам нужно переопределить метод reuseIdentifier, но он должен вернуть замененный идентификатор строка. Или, если он не указан, он должен вернуть класс в виде строки.
Что бы это ни стоило, я спросил об этом инженера iPhone на одном из технических обсуждений iPhone. Он ответил: «Да, возможно использовать IB для создания ячеек. Но не надо. Пожалуйста, не надо.
Я следовал инструкциям Apple, связанным с Беном Мошером (спасибо!), но обнаружил, что Apple пропустила важный момент. Объект, который они проектируют в IB, является просто UITableViewCell, как и переменная, которую они загружают из него. Но если вы фактически установите его как пользовательский подкласс UITableViewCell и напишите файлы кода для этого подкласса, вы можете написать объявления IBOutlet и методы IBAction в коде и связать их с вашими пользовательскими элементами в IB. Тогда нет необходимости использовать теги вида для доступа к этим элементам, и вы можете создать любую сумасшедшую ячейку, какую захотите. Это Какао Прикоснись к небесам.