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

324

Поэтому я делал 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 Reader [4390: c07] * Завершение приложения из-за необработанного исключения «NSInternalInconsistencyException», причина: «невозможно удалить из очереди ячейку с идентификатором 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) libc ++ abi.dylib: завершить вызов, выдав исключение

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

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

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

Ник Скотман
источник
возможный дубликат сбоя утверждения в UITableViewController
Venk

Ответы:

488

Вы используете dequeueReusableCellWithIdentifier:forIndexPath:метод. Документация для этого метода говорит , что это:

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

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

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

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

Обратите внимание, что dequeueReusableCellWithIdentifier:и dequeueReusableCellWithIdentifier:forIndexPath:это разные методы. Смотрите документ для первого и второго .

Если вы хотите понять, почему вы хотите использовать их dequeueReusableCellWithIdentifier:forIndexPath:, ознакомьтесь с этими вопросами и ответами .

Роб Майофф
источник
166
О, МОЙ БОГ. Почему шаблон Xcode по умолчанию для UITableViewController автоматически дает вам dequeueReusableCellWithIdentifier: forIndexPath :? Так бесполезно.
Спстанлей
15
dequeueReusableCellWithIdentifer:forIndexPath:(Введен в iOS6) является улучшение хорошо, так как вам не нужно , чтобы проверить , если ячейка равен нулю. (Так UITableViewControllerработает аналогично UICollectionView) Но да, раздражает то, что это изменение не является комментарием в шаблоне и что сообщение о подтверждении / сбое не является более полезным.
Джейсон Мур
2
По крайней мере, вы бы подумали, что по умолчанию будет UITableViewCell вместо взрыва. Бак.
BadPirate
13
Последняя строка этого ответа золотая: я был укушен не раз, dequeueReusableCellWithIdentifier:forIndexPath:когда использовал, когда я должен был использовать dequeueReusableCellWithIdentifier:.
Ele
Этот ответ идеален. У меня есть вопрос: у меня есть tableViewController в качестве моего начального контроллера представления. В didSelectRow ... Я помещаю другой tableViewController в стек навигации. Почему мне нужно только зарегистрировать ячейку для второго tableViewController, а не для начальной?
ArielSD
137

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

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

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

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


источник
3
Одна небольшая ошибка с этим - убедитесь, что идентификатор повторного использования совпадает с тем, что вы установили в настройках раскадровки для рассматриваемой ячейки.
Джеймс Бутчер
Просто чтобы добавить к этому немного другой вариант использования, я повторно выбирал строку в главном представлении моего SplitViewController. Эта логика повторного выбора строки была в viewDidLoadи перемещала эту логику, чтобы viewDidAppearисправить это.
Крейг Коновер,
Он не может войти в ячейку == ноль, поэтому моя ячейка таблицы всегда равна нулю.
Solid Soft,
3
swift 3.0: self.tableView.register (UITableViewCell.classForCoder (), forCellReuseIdentifier: "Cell");
norbDEV
68

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

Поэтому, если ваш CellIdentifier имеет значение «Cell», просто установите свойство «Identifier»: введите описание изображения здесь

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

Себастьян Борггреве
источник
3
ты потрясающий, уборка делает много !! : D
Сэнди
2
Примечание. Если вы используете идентификатор, отличный от «Cell», вам также потребуется изменить метод cellForRowAtIndexPath, чтобы использовать этот идентификатор в следующей строке: static NSString * CellIdentifier = @ "MyCellIdentifier";
gamozzii
5
Важное дополнение к этому: в табличном представлении должен быть установлен атрибут «Содержимое» «Динамические прототипы», а НЕ «Статические ячейки»
Тед Эйвери,
Этот ответ должен прийти выше. Очень полезно
Sukitha Udugamasooriya
Очистка сборки была необходима после обновления Identifierсобственности. Спасибо!
Crashalot
59

у меня была та же проблема с заменой на

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

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

    }

решена

iMeMyself
источник
Спасибо. Это только спасло меня от головной боли. =)
Роберт
3
Совет: если вы используете - (id) dequeueReusableCellWithIdentifier: forIndexPath:, вам не нужно проверять, равна ли ячейка нулю. (IOS6>)
seufagner,
только что спас меня от головной боли. =)
Abo3atef
26

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

Если вы создаете свой заказ, UITableViewControllerкак это:

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

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

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

Тогда вы сделали!

Джеймс Ван
источник
Совет, который используется instantiateViewControllerWithIdentifierдля инициализации моего viewController, спас мой день!
Лэй Чжан
спас мой день: прототип клетки находился в соседнем ВК с таблицей
Антон Тропашко
Это разумная причина в моем случае.
Нора Алнашван
19

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

Брайан Шрайвер
источник
Ужалил меня! Теперь я буду знать лучше. ;)
Спстанлей
18

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

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

Решение Swift 2.0:

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

введите описание изображения здесь

Затем вам нужно сделать так, чтобы ваш идентификатор соответствовал вашей очереди:

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 от Apple гласит:

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

Если вы ранее зарегистрировали файл класса или пера с тем же идентификатором повторного использования, класс, указанный в параметре 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)
Дэн Болье
источник
Я не понимаю, откуда SwitchCell.selfэто?
Герт Кайкенс
@GertCuykens SwitchCell - это мой пользовательский UITableViewCell
Дэн Болье
1
Я сейчас далеко от своего Mac, но я точно могу обновить его, когда вернусь домой.
Дэн Болье
1
UITableViewCell.selfКажется, что замена его на работает для меня. Возможно добавьте примечание в ответе
Герт Кайкенс
@GertCuykens спасибо за то, что указал на это, я изменил SwitchCell.self для UITableViewCell.self
Дэн Болье
3

Если вы собираетесь использовать пользовательские статические ячейки, просто прокомментируйте этот метод:

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

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

Франсиско Гутьеррес
источник
3

Я даю вам ответ в Objective C и Swift. До этого я хочу сказать

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

Итак, мы добавляем registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier:

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

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

Цель С

ОПЦИЯ 1:

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

ВАРИАНТ 2:

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

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

СВИФТ

ОПЦИЯ 1:

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

ВАРИАНТ 2:

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

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

user3182143
источник
3

Работа с 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
}
norbDEV
источник
2

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

Я настроил делегирование в файле h: @interface myViewController: UIViewController

У меня был исходный код данных в моей реализации, и все равно BOOM !, каждый раз сбой! СПАСИБО "xxd" (номер 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, если вы хотите привязать к нему всплывающее окно.

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

Симона
источник
2

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

static NSString *CellIdentifier = @"YourCellIdenifier";
honkskillet
источник
2

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

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

Может быть, это будет полезно для кого-то еще.

Кармена
источник
2

Я правильно все настроил в раскадровке и выполнил чистую сборку, но продолжал получать сообщение об ошибке « необходимо зарегистрировать перо или класс для идентификатора или подключить ячейку прототипа в раскадровке »

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

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

FrostyL
источник
1

Некоторым это может показаться глупым, но я понял. Я получал эту ошибку, и проблема для меня заключалась в том, что я пытался использовать статические ячейки, но затем динамически добавлять больше материала. Если вы вызываете этот метод, ваши клетки должны быть динамическими прототипами. Выберите ячейку в раскадровке и под инспектором Атрибутов самое первое говорит «Содержимое», и вы должны выбрать динамические прототипы, а не статические.

Чейз Робертс
источник
СПАСИБО! Это была именно моя проблема.
Исаия Тернер
1

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

DrustZ
источник
1

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

Анкит Гарг
источник
0

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

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

Меняя его на [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; ИСПРАВЛЕННУЮ МОЮ ПРОБЛЕМУ!

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

Offek
источник
0

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

viewDidLoad

метод.

tableView.registerClass(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "your_reuse_identifier")
arango_86
источник
-1

Натолкнулся на эту ошибку. Идентификатор повторного использования ячейки bc был ошибочным - ошибка новичка, но это происходит: 1. Делает так, что идентификатор повторного использования ячейки SURE не содержит орфографических ошибок или пропущенных букв. 2. В том же духе не забывайте подсчет капитализации. 3. Нули - это не «О» (О)

Джон Питтс
источник