Я могу создать пользовательские UITableViewCells и загрузить их просто отлично, используя технику, описанную в потоке, найденном в http://forums.macrumors.com/showthread.php?t=545061. Однако использование этого метода больше не позволяет вам инициализировать ячейку с помощью reuseIdentifier, что означает, что вам нужно создавать целые новые экземпляры каждой ячейки при каждом вызове. Кто-нибудь придумал хороший способ кешировать конкретные типы ячеек для повторного использования, но все же уметь создавать их в Interface Builder?
Загрузка многоразового UITableViewCell из ниба
Ответ 1
Просто реализуйте метод с соответствующей сигнатурой метода:
- (NSString *) reuseIdentifier {
return @"myIdentifier";
}
Ответ 2
Собственно, поскольку вы создаете ячейку в Interface Builder, просто установите там идентификатор повторного использования:
Или, если вы используете Xcode 4, проверьте вкладку инспектора атрибутов:
(Edit: После того, как XIB генерируется XCode, он содержит пустой UIView, но нам нужен UITableViewCell, поэтому вам нужно вручную удалить UIView и вставить ячейку Table View. Конечно, IB не будет показывать UITableViewCell параметры для UIView.)
Ответ 3
Теперь в iOS 5 для этого есть соответствующий метод UITableView:
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
Ответ 4
Я не могу вспомнить, где я первоначально нашел этот код, но он отлично работал для меня до сих пор.
- (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...
Ответ 5
Посмотрите на ответ, который я дал на этот вопрос:
Возможно ли создать подклассы NSCell в Interface Builder?
Не только возможно спроектировать UITableViewCell в IB, это желательно, потому что в противном случае вся ручная проводка и размещение нескольких элементов очень утомительна. Performaance прекрасен, пока вы стараетесь сделать все элементы непрозрачными, когда это возможно. Идентификатор повторного использования устанавливается в IB для свойств UITableViewCell, тогда вы используете соответствующий идентификатор повторного использования в коде при попытке удалить из очереди.
Я также слышал от некоторых из докладчиков на WWDC в прошлом году, что вы не должны делать ячейки таблицы в IB, но это нагрузка койки.
Ответ 6
Начиная с iOS около 4.0, в документах iOS есть специальные инструкции, которые делают эту работу супер-быстрой:
Прокрутите вниз до места, где говорится о подклассе UITableViewCell.
Ответ 7
Вот еще один вариант:
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;
}
}
Ответ 8
Метод Луи работал у меня. Это код, который я использую для создания UITableViewCell из nib:
- (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;
}
Ответ 9
Я создаю свои собственные ячейки представления аналогичным образом - кроме того, что я соединяю ячейку через IBOutlet.
Подход [nib objectAt...]
восприимчив к изменениям позиций элементов в массиве.
Подход UIViewController
хорош - просто попробовал, и он работает достаточно хорошо.
НО...
Во всех случаях конструктор initWithStyle
НЕ вызывается, поэтому инициализация по умолчанию не выполняется.
Я читал разные места об использовании initWithCoder
или awakeFromNib
, но никаких убедительных доказательств того, что любой из них является правильным способом.
Помимо явного вызова некоторого метода инициализации в методе cellForRowAtIndexPath
я еще не нашел ответа на этот вопрос.
Ответ 10
A назад я нашел отличную запись в блоге по этой теме в blog.atebits.com и с тех пор начал использовать класс Loren Brichter ABTableViewCell для сделайте все мои UITableViewCells.
В итоге вы получите простой контейнер UIView, чтобы поместить все ваши виджеты, а прокрутка - молниеносно.
Надеюсь, это полезно.
Ответ 11
Этот метод также работает и не требует фанки 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];
}
Ответ 12
- (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;
}
Ответ 13
Решение 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 - владелец файла.
Ответ 14
В документах UITableView относительно dequeueWithReuseIdentifier
: "Строка, идентифицирующая объект ячейки, который будет повторно использоваться. По умолчанию идентификатор многократно используемых ячеек является его именем класса, но вы можете изменить его на любое произвольное значение".
Переориентация -reuseIdentifer сама по себе рискованна. Что произойдет, если у вас есть два подкласса вашего подкласса ячеек, и используйте их оба в одном представлении таблицы? Если они отправляют вызов идентификатора повторного использования на супер, вы будете деактивировать ячейку неправильного типа.............. Я думаю, вам нужно переопределить метод reuseIdentifier, но вернуть ему вытесненный идентификатор строка. Или, если он не указан, верните класс в виде строки.
Ответ 15
Для чего это стоит, я спросил об этом инженера iPhone об этом на одном из iPhone Tech Talks. Его ответ был: "Да, возможно использовать IB для создания ячеек, но не надо. Пожалуйста, не надо".
Ответ 16
Я следил за инструкциями Apple, связанными с Бен Мошером (спасибо!), но обнаружил, что Apple пропустил важный момент. Объект, который они создают в IB, является только UITableViewCell, как и переменная, которую они загружают из нее. Но если вы действительно настроили его как пользовательский подкласс UITableViewCell и напишите файлы кода для подкласса, вы можете записать объявления IBOutlet и методы IBAction в коде и связать их с вашими настраиваемыми элементами в IB. Тогда нет необходимости использовать теги просмотра для доступа к этим элементам, и вы можете создать любую сумасшедшую ячейку, которую вы хотите. Это Cocoa Коснитесь небес.