Ошибка подтверждения в dequeueReusableCellWithIdentifier: forIndexPath:

303

Итак, я делал rss-ридер для своей школы и закончил код. Я проверил тест и дал мне эту ошибку. Вот код, на который он ссылается:

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = 
     [tableView dequeueReusableCellWithIdentifier:CellIdentifier 
                                     forIndexPath:indexPath];
    if (cell == nil) {

        cell = 
         [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle  
                                reuseIdentifier:CellIdentifier];

    }

здесь ошибка в выходе:

2012-10-04 20: 13: 05.356 Читатель [4390: c07] * Ошибка утверждения в - [UITableView dequeueReusableCellWithIdentifier: forIndexPath:],/SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:4460 2012-10-04 20: 13: 05.357 Читатель [4390: c07] * Завершение приложения из-за неотображения исключение "NSInternalInconsistencyException", причина: "невозможно dequeue ячейка с идентификатором Cell - необходимо зарегистрировать нить или класс для идентификатора или подключить прототип ячейки в раскадровке ' * Первый стек вызова броска: (0x1c91012 0x10cee7e 0x1c90e78 0xb64f35 0xc7d14 0x39ff 0xd0f4b 0xd101f 0xb980b 0xca19b 0x6692d 0x10e26b0 0x228dfc0 0x228233c 0x228deaf 0x1058cd 0x4e1a6 0x4ccbf 0x4cbd9 0x4be34 0x4bc6e 0x4ca29 0x4f922 0xf9fec 0x46bc4 0x47311 0x2cf3 0x137b7 0x13da7 0x14fab 0x26315 0x2724b 0x18cf8 0x1becdf9 0x1becad0 0x1c06bf5 0x1c06962 0x1c37bb6 0x1c36f44 0x1c36e1b 0x147da 0x1665c 0x2a02 0x2935) libС++ abi.dylib: завершение вызова throwing exception

и здесь код, который он показывает на экране ошибки:

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

Пожалуйста, помогите!

Теги:
uitableview

20 ответов

491
Лучший ответ

Используется метод dequeueReusableCellWithIdentifier:forIndexPath:. documentation для этого метода говорит следующее:

Важно: Перед вызовом этого метода необходимо зарегистрировать файл класса или nib с помощью метода registerNib:forCellReuseIdentifier: или registerClass:forCellReuseIdentifier:.

Вы не зарегистрировали ник или класс для идентификатора повторного использования "Cell".

Посмотрев на свой код, вы, похоже, ожидаете, что метод dequeue вернет nil, если у него нет ячейки, чтобы дать вам. Для этого вам нужно использовать dequeueReusableCellWithIdentifier::

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

Обратите внимание, что dequeueReusableCellWithIdentifier: и dequeueReusableCellWithIdentifier:forIndexPath: - разные методы. См. Doc для предыдущий и последний.

Если вы хотите понять, почему вы хотите когда-либо использовать dequeueReusableCellWithIdentifier:forIndexPath:, проверить этот Q & A.

  • 165
    О, МОЙ БОГ. Почему шаблон Xcode по умолчанию для UITableViewController автоматически дает вам dequeueReusableCellWithIdentifier: forIndexPath :? Так бесполезно.
  • 15
    Метод dequeueReusableCellWithIdentifer:forIndexPath: (представлен в iOS6) является хорошим улучшением, поскольку вам не нужно проверять, равна ли ячейка нулю. (Так что UITableViewController работает аналогично UICollectionView ) Но да, раздражает то, что это изменение не является комментарием в шаблоне и что сообщение о подтверждении / сбое не является более полезным.
Показать ещё 4 комментария
131

Я думаю, что эта ошибка связана с регистрацией вашего идентификатора или класса для идентификатора.

Чтобы вы могли сохранить то, что вы делаете в своей функции tableView: cellForRowAtIndexPath, и просто добавьте код в свой viewDidLoad:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];

Это сработало для меня. Надеюсь, это поможет.

  • 2
    Спасибо вам большое!
  • 3
    Одна маленькая ошибка с этим - убедитесь, что идентификатор повторного использования совпадает с тем, что вы установили в настройках раскадровки для рассматриваемой ячейки.
Показать ещё 3 комментария
64

Хотя этот вопрос довольно старый, есть еще одна возможность: Если вы используете раскадровки, вам просто нужно установить CellIdentifier в раскадровке.

Итак, если ваш CellIdentifier является "Cell", просто установите свойство "Идентификатор": Изображение 5556

Обязательно очистите свою сборку после этого. XCode иногда имеет некоторые проблемы с обновлениями раскадровки

  • 3
    ты потрясающий, уборка делает много !! : D
  • 2
    Примечание. Если вы используете идентификатор, отличный от «Cell», вам также потребуется изменить метод cellForRowAtIndexPath, чтобы использовать этот идентификатор в следующей строке: static NSString * CellIdentifier = @ "MyCellIdentifier";
Показать ещё 5 комментариев
56

У меня была проблема с заменой

static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

   if (cell==nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

    }

решена

  • 0
    Спасибо. Это только спасло меня от головной боли. знак равно
  • 0
    Это также спасло меня, спасибо!
Показать ещё 2 комментария
26

Проблема, скорее всего, потому, что вы настраиваете UITableViewCell в раскадровке, но не используете раскадровку для создания экземпляра UITableViewController, который использует этот UITableViewCell. Например, в MainStoryboard у вас есть подкласс UITableViewController под названием MyTableViewController и имеет пользовательский динамический UITableViewCell, называемый MyTableViewCell с идентификатором id MyCell.

Если вы создадите свой собственный UITableViewController следующим образом:

 MyTableViewController *myTableViewController = [[MyTableViewController alloc] init];

Он не будет автоматически регистрировать ваш пользовательский tableviewcell для вас. Вы должны вручную зарегистрировать его.

Но если вы используете раскадровку для создания экземпляра MyTableViewController, например:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MyTableViewController *myTableViewController = [storyboard  instantiateViewControllerWithIdentifier:@"MyTableViewController"];

Хорошая вещь случается! UITableViewController автоматически зарегистрирует вашу пользовательскую ячейку таблицы, которую вы определяете для раскадровки.

В методе делегата "cellForRowAtIndexPath" вы можете создать свою ячейку вида таблицы следующим образом:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

//Configure your cell here ...

return cell;
}

dequeueReusableCellWithIdentifier автоматически создаст новую ячейку для вас, если в очереди рециркуляции нет повторно используемой ячейки.

Тогда все готово!

  • 0
    Это был настоящий виновник, ура!
  • 0
    Совет, что использование instantiateViewControllerWithIdentifier для инициализации моего viewController спасло мой день!
Показать ещё 2 комментария
19

Я просто добавлю, что Xcode 4.5 включает новый dequeueReusableCellWithIdentifier:forIndexPath:
в своем шаблоне кода по умолчанию - потенциальная возможность для разработчиков, ожидающих более старый метод dequeueReusableCellWithIdentifier:.

  • 0
    Ужалил меня! Теперь я буду знать лучше. ;)
18

В своем раскадровке вы должны установить "Идентификатор" вашей ячейки прототипа, чтобы он был таким же, как и CellReuseIdentifier "Cell". Тогда вы не получите это сообщение или не должны будете называть эту функцию registerClass:.

  • 2
    Попался! Где кнопка «100 голосов». Это реальное решение.
  • 0
    Можно подумать, что добавление нового tableView в раскадровку предоставит для вас идентификатор по умолчанию - «Cell». Это так легко пропустить, особенно если вы используете так называемый «бесплатный код» в tableView: cellForRowAtIndexPath!
17

Решение Swift 2.0:

Вам нужно зайти в свой инспектор атрибутов и добавить имя для своих ячеек. Идентификатор:

Изображение 5557

Затем вам нужно сделать свой идентификатор совпадающим с вашим детектом следующим образом:

let cell2 = tableView.dequeueReusableCellWithIdentifier("ButtonCell", forIndexPath: indexPath) as! ButtonCell

В качестве альтернативы

Если вы работаете с наконечником, вам может потребоваться зарегистрировать свой класс в cellForRowAtIndexPath:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {       

    tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "SwitchCell")

    // included for context            
    let cell = tableView.dequeueReusableCellWithIdentifier("SwitchCell", forIndexPath:indexPath) as! SwitchCell

    //... continue    
}

Яблоки Справочник по классу UITableView говорит:

Перед тем, как удалить все ячейки, вызовите этот метод или registerNib: forCellReuseIdentifier: метод, чтобы показать представление таблицы как для создания новых ячеек. Если ячейка указанного типа в настоящий момент отсутствует в очереди повторного использования представление таблицы использует предоставленную информацию для автоматически создайте новый объект ячейки.

Если вы ранее зарегистрировали файл класса или nib с тем же повторным использованием идентификатор, класс, указанный вами в параметре cellClass, заменяет старая запись. Вы можете указать nil для cellClass, если хотите отменить регистрацию класса из указанного идентификатора повторного использования.

Здесь код из рамки Apples Swift 2.0:

// Beginning in iOS 6, clients can register a nib or class for each cell.
// If all reuse identifiers are registered, use the newer -dequeueReusableCellWithIdentifier:forIndexPath: to guarantee that a cell instance is returned.
// Instances returned from the new dequeue method will also be properly sized when they are returned.

@available(iOS 5.0, *)
func registerNib(nib: UINib?, forCellReuseIdentifier identifier: String)

@available(iOS 6.0, *)
func registerClass(cellClass: AnyClass?, forCellReuseIdentifier identifier: String)
  • 0
    Большое спасибо за это!!!!
  • 0
    Я не понимаю, откуда SwitchCell.self ?
Показать ещё 5 комментариев
3

Я даю вам ответ как в Objective C, так и в Swift. Прежде чем я хочу сказать

Если мы используем dequeueReusableCellWithIdentifier:forIndexPath:, мы должны зарегистрировать файл класса или nib, используя метод registerNib: forCellReuseIdentifier: или registerClass: forCellReuseIdentifier: перед вызовом этого метода как Apple Documnetation говорит

Итак, добавим registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier:

Как только мы зарегистрировали класс для указанного идентификатора и создадим новую ячейку, этот метод инициализирует ячейку, вызывая ее метод initWithStyle: reuseIdentifier:. Для ячеек, основанных на nib, этот метод загружает объект ячейки из предоставленного файла nib. Если существующая ячейка была доступна для повторного использования, этот метод вызывает метод prepareForReuse.

в методе viewDidLoad мы должны зарегистрировать ячейку

Цель C

ВАРИАНТ 1:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];

ВАРИАНТ 2:

[self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" bundle:nil] forCellReuseIdentifier:@"cell"];

в приведенном выше коде nibWithNibName:@"CustomCell" укажите имя nib вместо имени nib имя CustomCell

SWIFT

ВАРИАНТ 1:

tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")

ВАРИАНТ 2:

tableView.registerNib(UINib(nibName: "NameInput", bundle: nil), forCellReuseIdentifier: "Cell") 

в приведенном выше коде nibName:"NameInput" укажите имя пользователя

3

Если вы собираетесь с Custom Static Cells просто прокомментировать этот метод:

//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//    static NSString *CellIdentifier = @"notificationCell";
//    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//    return cell;
//}

и дать ячейкам идентификатор в "Инспектор атрибутов" в раскадровке.

2

Работа с Swift 3.0:

override func viewDidLoad() {
super.viewDidLoad()

self.myList.register(UINib(nibName: "MyTableViewCell", bundle: nil), forCellReuseIdentifier: "Cell")
}



public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myList.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) as! MyTableViewCell

return cell
}
2

У меня была такая же проблема, была такая же ошибка, и для меня она работала вот так:

[self.tableView registerNib:[UINib nibWithNibName:CELL_NIB_HERE bundle: nil] forCellReuseIdentifier:CELL_IDENTIFIER_HERE];

Возможно, это будет полезно для кого-то еще.

  • 1
    Это единственное, что сработало для меня!
2

Я правильно настроил все в раскадровке и сделал чистую сборку, но продолжал получать ошибку "должен зарегистрировать ниб или класс для идентификатора или подключить прототип ячейки в раскадровке"

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];

Исправлена ​​ошибка, но я все еще не в порядке. Я не использую "пользовательскую ячейку", просто представление с встроенным табличным представлением. Я объявил viewcontroller как делегат и источник данных и убедился, что идентификатор ячейки совпадает с файлом. Что здесь происходит?

2

FWIW, я получил ту же ошибку, когда забыл установить идентификатор ячейки в раскадровке. Если это ваша проблема, тогда в раскадровке щелкните ячейку просмотра таблицы и установите идентификатор ячейки в редакторе атрибутов. Убедитесь, что идентификатор ячейки, указанный здесь, совпадает с

static NSString *CellIdentifier = @"YourCellIdenifier";
2

Я провел часы вчера вечером, выясняя, почему моя программно сгенерированная таблица разбилась на [myTable setDataSource: self]; Это было ОК, комментируя и всплывая пустую таблицу, но разбился каждый раз, когда я пытался добраться до источника данных;

У меня была команда, настроенная в файле h: @interface myViewController: UIViewController

У меня был исходный код данных в моей реализации и все еще BOOM!, сбой каждый раз! СПАСИБО к "xxd" (nr 9): добавив, что строка кода решила его для меня! На самом деле я запускаю таблицу из кнопки IBAction, так что вот мой полный код:

    - (IBAction)tapButton:(id)sender {

    UIViewController* popoverContent = [[UIViewController alloc]init];

    UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)];
    popoverView.backgroundColor = [UIColor greenColor];
    popoverContent.view = popoverView;

    //Add the table
    UITableView *table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)         style:UITableViewStylePlain];

   // NEXT THE LINE THAT SAVED MY SANITY Without it the program built OK, but crashed when      tapping the button!

    [table registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
    table.delegate=self;
    [table setDataSource:self];
    [popoverView addSubview:table];
    popoverContent.contentSizeForViewInPopover =
    CGSizeMake(200, 300);

    //create a popover controller
    popoverController3 = [[UIPopoverController alloc]
                          initWithContentViewController:popoverContent];
    CGRect popRect = CGRectMake(self.tapButton.frame.origin.x,
                                self.tapButton.frame.origin.y,
                                self.tapButton.frame.size.width,
                                self.tapButton.frame.size.height);


    [popoverController3 presentPopoverFromRect:popRect inView:self.view   permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];



   }


   #Table view data source in same m file

   - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
   {
    NSLog(@"Sections in table");
    // Return the number of sections.
    return 1;
   }

   - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
  {
    NSLog(@"Rows in table");

    // Return the number of rows in the section.
    return myArray.count;
   }

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath    *)indexPath
    {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    NSString *myValue;

    //This is just some test array I created:
    myValue=[myArray objectAtIndex:indexPath.row];

    cell.textLabel.text=myValue;
    UIFont *myFont = [ UIFont fontWithName: @"Arial" size: 12.0 ];
    cell.textLabel.font  = myFont;

    return cell;
   }

Кстати: кнопка должна быть связана с IBAction и как IBOutlet, если вы хотите привязать к ней popover.

UIPopoverController * popoverController3 объявляется в файле H непосредственно после @interface между {}

1

Убедитесь, что идентификатор CellIdentifier == ячейки в раскадровке, оба имени одинаковы. Надеюсь, что это работает для u

1

Просто добавление ответов: Возможно, вам придет время, когда вы все исправите правильно, но вы можете случайно добавить в себя другие пользовательские интерфейсы .xib, например UIButton: Изображение 5558 Просто удалите дополнительный интерфейс, он работает.

  • 0
    это работает для меня, как очень хорошо. Благодарю.
1

Это может показаться глупым для некоторых людей, но это меня достало. Я получал эту ошибку, и проблема для меня заключалась в том, что я пытался использовать статические ячейки, но затем динамически добавлял больше вещей. Если вы вызываете этот метод, ваши ячейки должны быть динамическими прототипами. Выберите ячейку в раскадровке и под инспектором атрибутов, самое первое - "Контент", и вы должны выбрать динамические прототипы, не статические.

  • 0
    БЛАГОДАРЮ ВАС! Это была именно моя проблема.
0

В Swift эту проблему можно решить, добавив следующий код в свой

viewDidLoad

метод.

tableView.registerClass(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "your_reuse_identifier")
0

В моем случае авария произошла, когда я позвонил deselectRowAtIndexPath:

Линия была [tableView deselectRowAtIndexPath:indexPath animated:YES];

Изменение его на [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; ФИКСИРОВАННАЯ МОЯ ПРОБЛЕМА!

Надеюсь, это поможет кому-то

Ещё вопросы

Сообщество Overcoder
Наверх
Меню