ChatGPT解决这个技术问题 Extra ChatGPT

dequeueReusableCellWithIdentifier:forIndexPath 中的断言失败:

所以我正在为我的学校制作一个 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”而终止应用程序,原因:“无法使具有标识符 Cell 的单元格出列 - 必须为标识符注册一个 nib 或一个类或连接故事板中的原型单元格' * First throw call stack: (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]));
    }
}

请帮忙!


C
Community

您正在使用 dequeueReusableCellWithIdentifier:forIndexPath: 方法。该方法的 documentation 表示:

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

您没有为重用标识符 "Cell" 注册 nib 或类。

查看您的代码,您似乎希望 dequeue 方法返回 nil 如果它没有单元格可以给您。对于该行为,您需要使用 dequeueReusableCellWithIdentifier:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

请注意,dequeueReusableCellWithIdentifier:dequeueReusableCellWithIdentifier:forIndexPath: 是不同的方法。请参阅 the formerthe latter 的文档。

如果您想了解为什么要使用 dequeueReusableCellWithIdentifier:forIndexPath:check out this Q&A


我的天啊。为什么 Xcode 的 UITableViewController 的默认模板会自动为您提供 dequeueReusableCellWithIdentifier:forIndexPath:?太没用了。
dequeueReusableCellWithIdentifer:forIndexPath:(在 iOS6 中引入)是一个很好的改进,因为您不需要检查单元格是否为 nil。 (所以 UITableViewController 的工作方式类似于 UICollectionView)但是,是的,令人讨厌的是,此更改没有在模板中注释,并且断言/崩溃消息没有更多帮助。
至少你会认为它会默认为 UITableViewCell 而不是内爆。巴卡。
这个答案的最后一行是金句:当我应该使用 dequeueReusableCellWithIdentifier: 时,我已经不止一次使用 dequeueReusableCellWithIdentifier:forIndexPath: 被咬了。
这个答案很完美。我有一个问题:我有一个 tableViewController 作为我的初始视图控制器。在 didSelectRow... 我将另一个 tableViewController 推到导航堆栈上。为什么我只需要为第二个 tableViewController 注册一个单元格,而不是初始?
佚名

我认为这个错误是关于为标识符注册你的笔尖或类。

这样您就可以在 tableView:cellForRowAtIndexPath 函数中保留您正在做的事情,只需将以下代码添加到您的 viewDidLoad 中:

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

它对我有用。希望它可能会有所帮助。


一个小问题 - 确保重用标识符与您在故事板设置中为相关单元格设置的内容相匹配。
只是为了在稍微不同的用例中添加这一点,我在我的 SplitViewController 的主视图中重新选择了一行。此重新选择行逻辑位于 viewDidLoad 中,并将此逻辑移至 viewDidAppear 修复了它。
它无法进入 cell==nil ,所以我的 tableview 单元格始终为零。
swift 3.0: self.tableView.register(UITableViewCell.classForCoder(), forCellReuseIdentifier:"Cell");
S
Sebastian Borggrewe

虽然这个问题已经相当老了,但还有另一种可能性:如果您使用的是 Storyboard,您只需在 Storyboard 中设置 CellIdentifier。

https://i.stack.imgur.com/uBGUN.png

确保在这样做之后清理你的构建。 XCode 有时会在 Storyboard 更新方面出现一些问题


你太棒了,清洁很重要! :D
注意 - 如果您使用“Cell”以外的标识符,您还需要更改 cellForRowAtIndexPath 方法以在以下行中使用此标识符: static NSString *CellIdentifier = @"MyCellIdentifier";
对此的一个重要补充:表格视图必须将其“内容”属性设置为“动态原型”,而不是“静态单元格”
这个答案需要更高。非常有帮助
更新 Identifier 属性后,清理构建是必不可少的。谢谢!
i
iMeMyself

我有同样的问题替换

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

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

    }

解决了


谢谢你。这只是让我头疼。 =)
提示:如果您使用 -(id)dequeueReusableCellWithIdentifier:forIndexPath:,则不需要验证单元格是否为零。 (IOS6>)
只是让我头疼。 =)
S
Soumya Ranjan

问题很可能是因为您在情节提要中配置了自定义 UITableViewCell,但您没有使用情节提要来实例化使用此 UITableViewCellUITableViewController。例如,在 MainStoryboard 中,您有一个名为 MyTableViewControllerUITableViewController 子类和一个名为 MyTableViewCell 的自定义动态 UITableViewCell,标识符 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 将自动为您创建新单元格。

然后你就完成了!


使用 instantiateViewControllerWithIdentifier 来初始化我的 viewController 的提示拯救了我的一天!
拯救了我的一天:原型单元在相邻的 VC 中,有一张桌子
在我的情况下,这是合理的原因。
S
Sangram Shivankar

我将补充一点,Xcode 4.5 在其默认模板代码中包含新的 dequeueReusableCellWithIdentifier:forIndexPath:
- 对于期待旧 dequeueReusableCellWithIdentifier: 方法的开发人员来说,这是一个潜在的陷阱。


蜇了我!现在我会知道的更好。 ;)
S
Steven

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


明白了! “100 upvotes”按钮在哪里。这是真正的解决方案。
您会认为将新的 tableView 添加到情节提要中将为您提供默认标识符 - 'Cell'。它很容易被忽视,特别是如果您在 tableView:cellForRowAtIndexPath 中使用所谓的“免费代码”!
D
Dan Beaulieu

斯威夫特 2.0 解决方案:

您需要进入属性检查器并为您的单元格标识符添加一个名称:

https://i.stack.imgur.com/Q9Miq.png

然后你需要让你的标识符与你的出队匹配,如下所示:

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

或者

如果您正在使用 nib,您可能需要在 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    
}

Apples's UITableView Class Reference says:

在将任何单元格出列之前,调用此方法或 registerNib:forCellReuseIdentifier: 方法来告诉表格视图如何创建新单元格。如果指定类型的单元格当前不在重用队列中,则表格视图使用提供的信息自动创建新的单元格对象。如果您之前使用相同的重用标识符注册了类或 nib 文件,则您在 cellClass 参数中指定的类将替换旧条目。如果你想从指定的重用标识符中注销类,你可以为 cellClass 指定 nil。

以下是 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
我现在不在我的 Mac 上,但我回家后肯定可以更新它。
UITableViewCell.self 替换它似乎对我有用。也许在答案中添加注释
@GertCuykens 感谢您指出这一点,我已将 SwitchCell.self 更改为 UITableViewCell.self
F
Francisco Gutiérrez

如果您要使用自定义静态单元格,只需评论此方法:

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

并在情节提要的“属性检查器”处为单元格指定一个标识符。


u
user3182143

我在 Objective C 和 Swift 中都给你答案。在此之前我想说

如果我们使用 dequeueReusableCellWithIdentifier:forIndexPath:,我们必须在调用此方法之前使用 registerNib:forCellReuseIdentifier: 或 registerClass:forCellReuseIdentifier: 方法注册一个类或 nib 文件,如 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" 中,提供您的笔尖名称而不是我的笔尖名称 CustomCell

迅速

选项1:

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

选项 2:

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

在上面的代码 nibName:"NameInput" 中给出你的笔尖名称


n
norbDEV

使用 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
}

S
Simone

昨晚我花了几个小时弄清楚为什么我以编程方式生成的表在 [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 在H文件中直接声明在{}之间的@interface之后


h
honkskillet

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

static NSString *CellIdentifier = @"YourCellIdenifier";

C
CarmenA

我有同样的问题,有同样的错误,对我来说它是这样工作的:

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

也许它对其他人有用。


U
Undo

我在情节提要中正确设置了所有内容并进行了干净的构建,但不断收到错误“必须为标识符注册笔尖或类或在情节提要中连接原型单元”

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

纠正了错误,但我仍然不知所措。我没有使用“自定义单元格”,只是一个嵌入了 tableview 的视图。我已将视图控制器声明为委托和数据源,并确保单元格标识符在文件中匹配。这里发生了什么?


C
Chase Roberts

这对某些人来说可能看起来很愚蠢,但它让我明白了。我收到了这个错误,对我来说问题是我试图使用静态单元格,然后动态添加更多内容。如果您调用此方法,您的单元格需要是动态原型。选择情节提要中的单元格并在属性检查器下,第一件事是“内容”,您应该选择动态原型而不是静态的。


谢谢你!这正是我的问题。
D
DrustZ

https://i.stack.imgur.com/vVwra.png


g
garg

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


O
Offek

就我而言,崩溃发生在我打电话时deselectRowAtIndexPath:

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

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

希望这对任何人都有帮助


a
arango_86

在 Swift 中,这个问题可以通过在你的

viewDidLoad

方法。

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

O
Ol Sen

您必须注意,在使用 interface builder 并创建一个包含 一个 单元格的 Xib(笔尖)时,还会创建一个指向将要使用的类的 placeholder。这意味着,当您将两个 UITableViewCell 放在一个 Xib 文件中时,您可能会遇到完全相同的问题,从而导致 *** Assertion failure ...。占位符机制不起作用,然后会感到困惑。而是在一个 Xib 中放置不同的占位符。

最简单的解决方案(即使这看起来有点简单)是在一个 Xib 中一次放置一个 Cell。 IB 将为您创建一个占位符,然后所有工作都按预期进行。但这会直接导致一行额外的代码,因为您需要加载正确的 nib/xib 以请求其所在的重用标识单元。因此,以下示例代码集中在一个表视图中使用多个单元标识符,其中断言失败很常见。

// possibly above class implementation
static NSString *firstCellIdentifier = @"firstCellIdentifier";
static NSString *secondCellIdentifier = @"secondCellIdentifier";

// possibly in -(instancetype)init 
UINib *firstNib = [UINib nibWithNibName:@"FirstCell" bundle:nil];
[self.tableView registerNib:firstNib forCellReuseIdentifier:firstCellIdentifier];
UINib *secondNib = [UINib nibWithNibName:@"SecondCell" bundle:nil];
[self.tableView registerNib:secondNib forCellReuseIdentifier:secondCellIdentifier];

在一个 UITableView 中使用两个 CellIdentifier 的另一个问题是必须注意行高和/或节高。当然,两个单元格可以有不同的高度。

在注册类以供重用时,代码应该看起来不同。

当您的单元位于 Storyboard 而不是 Xib 中时,“简单解决方案”看起来也大不相同。注意占位符。

还要记住,界面构建器文件具有版本变化,需要设置为您的目标操作系统版本支持的版本。即使您可能很幸运,您在 Xib 中放置的特定功能自上一个 IB 版本以来没有更改,并且还没有引发错误。因此,使用设置为与 iOS 13+ 兼容的 IB 制作的 Xib 但用于在早期版本 iOS 12.4 上编译的目标也会引起麻烦并最终导致断言失败。


J
John Pitts

遇到此错误,因为单元格重用标识符错误 - 一个新手错误,但它发生了: 1. 确保单元格重用标识符没有拼写错误或缺少字母。 2. 同样,不要忘记大小写计数。 3. 零不是“O”(哦)


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅