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 Reader [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]));
    }
}

请帮忙!


Answers:


488

您正在使用该dequeueReusableCellWithIdentifier:forIndexPath:方法。该方法的文档说明:

重要提示:调用此方法之前,必须使用registerNib:forCellReuseIdentifier:registerClass:forCellReuseIdentifier:方法注册类或nib文件。

您没有为重用标识符注册笔尖或类"Cell"

查看您的代码,您似乎期望dequeue方法在nil没有单元格的情况下返回。您需要dequeueReusableCellWithIdentifier:针对该行为使用:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

请注意,dequeueReusableCellWithIdentifier:dequeueReusableCellWithIdentifier:forIndexPath:是不同的方法。前者后者参见doc 。

如果您想了解为什么要使用dequeueReusableCellWithIdentifier:forIndexPath:请查看此问答


166
我的天啊。为什么Xcode的UITableViewController的默认模板会自动为您提供dequeueReusableCellWithIdentifier:forIndexPath :?太无益了。
spstanley 2012年

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的Master视图中重新选择了一行。此重新选择行逻辑位于中,viewDidLoad并将其移动以viewDidAppear对其进行修复。
Craig Conover

它无法输入cell == nil,所以我的tableview单元始终为nil。
Solid Soft

3
迅捷的3.0:self.tableView.register(UITableViewCell.classForCoder(),forCellReuseIdentifier:“ Cell”);
norbDEV

68

尽管这个问题已经很久了,但是还有另一种可能性:如果使用情节提要,只需在情节提要中设置CellIdentifier。

因此,如果您的CellIdentifier是“ Cell”,则只需设置“ Identifier”属性即可: 在此处输入图片说明

确保这样做后清洁构建。XCode有时在Storyboard更新方面存在一些问题


3
你真棒,清洁很多!:D
桑迪

2
注意-如果使用的标识符不是“ Cell”,则还需要更改cellForRowAtIndexPath方法以在以下行中使用此标识符:static NSString * CellIdentifier = @“ MyCellIdentifier”;
gamozzii

5
一个重要的补充:表格视图必须将其“内容”属性设置为“动态原型”,而不是“静态单元格”
Ted Avery 2014年

这个答案需要更高。非常有帮助
Sukitha Udugamasooriya 2014年

更新Identifier酒店后,清理房屋至关重要。谢谢!
Crashalot 2015年

59

我有同样的问题替换

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

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

    }

解决了


谢谢。这只是让我头疼。=)
罗伯特·

3
提示:如果您使用-(id)dequeueReusableCellWithIdentifier:forIndexPath:,则无需验证单元格是否为零。(IOS6>)
seufagner

只是让我头疼。=)
Abo3atef 2014年

26

问题很可能是因为您UITableViewCell在情节提要中配置了custom ,但没有使用情节提要来实例化UITableViewController使用this的实例UITableViewCell。例如,在MainStoryboard中,您有一个UITableViewController名为的子类,MyTableViewController并且有一个UITableViewCell名为MyTableViewCellID为“ 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将自动为您创建新的单元。

那您就完成了!


在使用尖端instantiateViewControllerWithIdentifier给init的viewController我救了我的天!
张磊

挽救了我的一天:原型单元放在桌子旁的VC中
Anton Tropashko

就我而言,这是合理的原因。
Nora Alnashwan '16

19

我将添加Xcode 4.5dequeueReusableCellWithIdentifier:forIndexPath:
在其默认模板代码中包括新代码-对于期望使用旧dequeueReusableCellWithIdentifier:方法的开发人员来说,这可能是一个陷阱。


ung死我了!现在我会更好了。;)
spstanley 2012年

18

在情节提要中,应将原型单元的“标识符”设置为与CellReuseIdentifier“单元”相同。然后,您将不会收到该消息,也不需要调用该registerClass:函数。


2
知道了!“ 100 upvotes”按钮在哪里。这是真正的解决方案。
Jojo.Lechelt 2013年

您会认为向情节提要中添加新的tableView将为您提供默认标识符-“单元格”。它很容易被忽略,特别是如果您在tableView:cellForRowAtIndexPath中使用所谓的“免费代码”!
ushika 2013年

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类参考说:

在使任何单元出队之前,请调用此方法或registerNib:forCellReuseIdentifier:方法来告诉表视图如何创建新单元。如果指定类型的单元格当前不在重用队列中,则表视图将使用提供的信息自动创建新的单元格对象。

如果您先前使用相同的重用标识符注册了一个类或nib文件,则在cellClass参数中指定的类将替换旧条目。如果要从指定的重用标识符中注销该类,则可以为cellClass指定nil。

这是来自Apple 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
Gert Cuykens 2015年

@GertCuykens SwitchCell是我自定义的UITableViewCell
Dan Beaulieu

1
我现在不在使用Mac,但是回家后绝对可以对其进行更新。
Dan Beaulieu 2015年

1
替换它UITableViewCell.self似乎对我有用。也许增加一个音符的答案
格特Cuykens

@GertCuykens感谢您指出,我已将SwitchCell.self更改为UITableViewCell.self
Dan Beaulieu

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:方法注册类或nib文件,然后再将其称为 Apple Documnetation说

所以我们添加 registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier:

一旦我们为指定的标识符注册了一个类并且必须创建一个新的单元格,此方法将通过调用其initWithStyle:reuseIdentifier:方法来初始化该单元格。对于基于笔尖的单元格,此方法从提供的笔尖文件中加载单元格对象。如果现有单元可供重用,则此方法改为调用单元的prepareForReuse方法。

在viewDidLoad方法中,我们应该注册单元格

目标C

选项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"您的笔尖名称


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
}

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链接起来。

UIPopoverController * popoverController3在{}之间的@interface之后直接在H文件中声明


2

FWIW,当我忘记在情节提要中设置单元格标识符时,出现了同样的错误。如果这是您的问题,请在情节提要中单击表格视图单元格,然后在属性编辑器中设置单元格标识符。确保您在此处设置的单元格标识符与

static NSString *CellIdentifier = @"YourCellIdenifier";

2

我遇到了同样的问题,遇到了同样的错误,对我来说,它像这样工作:

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

也许对其他人有用。


2

我在情节提要板上正确设置了所有内容,并进行了干净的构建,但始终出现错误“ 必须注册一个笔尖或一个类作为标识符,或在情节提要中连接原型单元

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

更正了错误,但我仍然茫然。我不是在使用“自定义单元格”,而是嵌入了表格视图的视图。我已将viewcontroller声明为委托和数据源,并确保单元格标识符与文件中的匹配。这里发生了什么?


1

对某些人来说,这可能看起来很愚蠢,但它吸引了我。我收到此错误,对我来说,问题是我尝试使用静态单元格,然后动态添加更多内容。如果调用此方法,则您的单元格必须是动态原型。在情节提要板中,在“属性”检查器下选择单元格,首先要说“内容”,然后应选择动态原型而不是静态原型。


谢谢!这正是我的问题。
以赛亚·特纳

1

只是对问题的补充:有时可能您将所有事情都设置正确,但是您可能会不小心在其中添加了其他一些UI .xib,例如UIButton在此处输入图片说明 仅删除多余的UI,它就可以了。


1

确保故事板上的单元格的CellIdentifier ==标识符,两个名称相同。希望这对你有用


0

就我而言,当我打电话时发生了车祸deselectRowAtIndexPath:

该行是 [tableView deselectRowAtIndexPath:indexPath animated:YES];

将其更改为已[self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 解决我的问题!

希望这对任何人有帮助


0

在Swift中,可以通过在您的计算机中添加以下代码来解决此问题

viewDidLoad

方法。

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

-1

遇到此错误,因为bc单元重用标识符是错误的-一个菜鸟错误,但它发生了:1.确保SURE单元重用标识符没有拼写错误或字母丢失。2.同样,不要忘记大写计数。3.零不是“ O”(Ohs)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.