Загрузка многоразового UITableViewCell из ниба

Я могу создать пользовательские UITableViewCells и загрузить их просто отлично, используя технику, описанную в потоке, найденном в http://forums.macrumors.com/showthread.php?t=545061. Однако использование этого метода больше не позволяет вам инициализировать ячейку с помощью reuseIdentifier, что означает, что вам нужно создавать целые новые экземпляры каждой ячейки при каждом вызове. Кто-нибудь придумал хороший способ кешировать конкретные типы ячеек для повторного использования, но все же уметь создавать их в Interface Builder?

Ответ 1

Просто реализуйте метод с соответствующей сигнатурой метода:

- (NSString *) reuseIdentifier {
  return @"myIdentifier";
}

Ответ 2

Собственно, поскольку вы создаете ячейку в Interface Builder, просто установите там идентификатор повторного использования:

IB_reuse_identifier

Или, если вы используете Xcode 4, проверьте вкладку инспектора атрибутов:

enter image description here

(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...

alt text

Ответ 5

Посмотрите на ответ, который я дал на этот вопрос:

Возможно ли создать подклассы NSCell в Interface Builder?

Не только возможно спроектировать UITableViewCell в IB, это желательно, потому что в противном случае вся ручная проводка и размещение нескольких элементов очень утомительна. Performaance прекрасен, пока вы стараетесь сделать все элементы непрозрачными, когда это возможно. Идентификатор повторного использования устанавливается в IB для свойств UITableViewCell, тогда вы используете соответствующий идентификатор повторного использования в коде при попытке удалить из очереди.

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

Ответ 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 Коснитесь небес.