Вопрос

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

Это было полезно?

Решение

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

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

Другие советы

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

 IB_reuse_identifier

Или, если вы работаете в 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 ...

 alt text

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

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

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

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

Начиная с iOS 4.0, в документации для iOS есть специальные инструкции, которые делают эту работу очень быстрой:

http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7

Прокрутите вниз, где говорится о создании подкласса 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. Тогда нет необходимости использовать теги вида для доступа к этим элементам, и вы можете создать любую сумасшедшую ячейку, какую захотите. Это Какао Прикоснись к небесам.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top