所以我为我的学校制作了一个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对单元格进行出列 - 必须注册一个笔尖或类 标识符或连接故事板中的原型单元格 * 第一次抛出调用堆栈:(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:terminate调用抛出异常
以下是错误屏幕中显示的代码:
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
请帮忙!
答案 0 :(得分:483)
您正在使用dequeueReusableCellWithIdentifier:forIndexPath:
方法。该方法的documentation说明了这一点:
重要提示:在调用此方法之前,您必须使用
registerNib:forCellReuseIdentifier:
或registerClass:forCellReuseIdentifier:
方法注册类或nib文件。
您没有为重用标识"Cell"
注册一个nib或类。
查看您的代码,您似乎希望dequeue方法返回nil
,如果它没有单元格给您。您需要使用dequeueReusableCellWithIdentifier:
来表示该行为:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
请注意,dequeueReusableCellWithIdentifier:
和dequeueReusableCellWithIdentifier:forIndexPath:
是不同的方法。请参阅the former和the latter的文档。
如果您想了解为什么要使用dequeueReusableCellWithIdentifier:forIndexPath:
,check out this Q&A。
答案 1 :(得分:137)
我认为这个错误是关于为标识符注册你的笔尖或类。
这样你就可以在tableView:cellForRowAtIndexPath函数中保留你正在做的事情,只需将下面的代码添加到viewDidLoad中:
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
这对我有用。希望它可能有所帮助。
答案 2 :(得分:67)
虽然这个问题相当陈旧,但还有另一种可能性: 如果您使用的是Storyboard,则只需在Storyboard中设置CellIdentifier即可。
因此,如果您的CellIdentifier是“Cell”,只需设置“Identifier”属性:
确保在完成后清理您的构建。 XCode有时会在Storyboard更新中遇到一些问题
答案 3 :(得分:59)
我用
替换了同样的问题static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
解决
答案 4 :(得分:25)
问题很可能是因为您在故事板中配置了自定义UITableViewCell
,但您没有使用故事板来实例化使用此UITableViewController
的{{1}}。例如,在MainStoryboard中,您有一个名为UITableViewCell
的{{1}}子类,并且具有名为UITableViewController
的自定义动态MyTableViewController
,其标识符为“MyCell”。
如果您按照以下方式创建自定义UITableViewCell
:
MyTableViewCell
它不会自动为您注册自定义tableviewcell。你必须手动注册它。
但是如果你使用故事板来实例化UITableViewController
,就像这样:
MyTableViewController *myTableViewController = [[MyTableViewController alloc] init];
好的事情发生了! MyTableViewController
会自动注册您在故事板中定义的自定义tableview单元格。
在您的委托方法“cellForRowAtIndexPath”中,您可以像这样创建表格视图单元格:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MyTableViewController *myTableViewController = [storyboard instantiateViewControllerWithIdentifier:@"MyTableViewController"];
如果回收队列中没有可重复使用的单元,dequeueReusableCellWithIdentifier将自动为您创建新单元格。
然后你就完成了!
答案 5 :(得分:19)
我只想添加 Xcode 4.5 包含新的dequeueReusableCellWithIdentifier:forIndexPath:
在其默认模板代码中 - 开发人员期望使用较旧的dequeueReusableCellWithIdentifier:
方法的潜在问题。
答案 6 :(得分:18)
在故事板中,您应该将原型单元格的“标识符”设置为与CellReuseIdentifier“Cell”相同。然后你不会得到那条消息或需要调用registerClass:function。
答案 7 :(得分:18)
您需要进入属性检查器并为您的单元格标识符添加名称:
然后你需要让你的标识符与你的队列匹配:
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
}
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)
答案 8 :(得分:3)
如果你选择自定义静态单元格,只需评论此方法:
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// static NSString *CellIdentifier = @"notificationCell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// return cell;
//}
并在故事板中为“属性检查器”提供标识符。
答案 9 :(得分: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
}
答案 10 :(得分:3)
我在Objective C和Swift中给出了答案。在我想说之前
如果我们使用
dequeueReusableCellWithIdentifier:forIndexPath:
,我们必须在调用此方法之前使用registerNib:forCellReuseIdentifier:或registerClass:forCellReuseIdentifier:方法注册类或nib文件 Apple Documnetation Says
所以我们添加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
SWIFT
选项1:
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
选项2:
tableView.registerNib(UINib(nibName: "NameInput", bundle: nil), forCellReuseIdentifier: "Cell")
上面的代码nibName:"NameInput"
中的给出你的笔尖名称
答案 11 :(得分: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文件中声明答案 12 :(得分:2)
FWIW,当我忘记在故事板中设置单元格标识符时,我收到同样的错误。如果这是您的问题,则在故事板中单击表视图单元格并在属性编辑器中设置单元格标识符。确保您在此处设置的单元格标识符与
相同static NSString *CellIdentifier = @"YourCellIdenifier";
答案 13 :(得分:2)
我在Storyboard中正确设置了所有内容,并进行了干净的构建,但仍然收到错误“必须为标识符注册一个nib或类或在故事板中连接原型单元”
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
纠正了错误,但我仍然处于亏损状态。我没有使用'自定义单元',只是一个嵌入了tableview的视图。我已将viewcontroller声明为委托和数据源,并确保单元标识符在文件中匹配。什么事发生在这里?
答案 14 :(得分:2)
我有同样的问题,有同样的错误,对我来说它的工作原理如下:
[self.tableView registerNib:[UINib nibWithNibName:CELL_NIB_HERE bundle: nil] forCellReuseIdentifier:CELL_IDENTIFIER_HERE];
也许它会对其他人有用。
答案 15 :(得分:1)
这对某些人来说可能看起来很愚蠢,但它让我受益匪浅。我收到了这个错误,问题在于我是在尝试使用静态单元格,然后动态添加更多内容。如果您正在调用此方法,则您的单元格需要是动态原型。在故事板中选择单元格,在属性检查器下,首先要说的是“内容”,您应该选择不是静态的动态原型。
答案 16 :(得分:1)
确保故事板中CellIdentifier ==单元格的标识符,两个名称相同。希望这适用于你
答案 17 :(得分:1)
答案 18 :(得分:0)
在Swift中,可以通过在
中添加以下代码来解决此问题viewDidLoad中
方法
tableView.registerClass(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "your_reuse_identifier")
答案 19 :(得分:0)
就我而言,当我拨打deselectRowAtIndexPath:
这一行是[tableView deselectRowAtIndexPath:indexPath animated:YES];
将其更改为[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
修复我的问题!
希望这有助于任何人
答案 20 :(得分:0)
您必须注意,在使用interface builder
并创建包含一个单元格的Xib
(笔尖)时,还会创建一个{到将要使用的类。这意味着,当您将两个placeholder
放在一个Xib文件中时,可能会遇到完全相同的麻烦,从而导致UITableViewCell
。占位符机制不起作用,然后会感到困惑。而是将不同的占位符放在一个Xib中继续阅读。.
最简单的解决方案(即使看起来似乎很简单)是一次将一个单元格放在一个Xib 中。 IB将为您创建一个占位符,然后按预期进行所有工作。但这然后直接导致了另一行代码,因为然后您需要加载正确的nib / xib并询问其所在的reuseIdentified Cell。 因此,以下示例代码着重在一个断言非常普遍的表视图中使用多个单元格标识符。
*** Assertion failure ...
在一个UITableView中使用两个CellIdentifier的另一个麻烦是必须注意行高和/或节高。当然,两个单元的高度可以不同。
为重用注册类时,代码应该看起来有所不同。
当您的单元位于故事板而不是Xib时,“简单解决方案”看起来也大不相同。注意占位符。
还请记住,界面生成器文件具有版本明智的变体,需要将其设置为目标OS版本支持的版本。即使您很幸运,自从上一个IB版本以来,您放置在Xib中的特定功能也没有更改,并且还没有引发错误。因此,将IB制成的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];
兼容,但将其用于在较早版本iOS 13+
上编译的目标中,也将造成麻烦,并最终导致断言失败。
答案 21 :(得分:-1)
总是总是总是检查最明显的事情:
首先检查。我怀疑这可能是问题所在,但只是假设我没有忘记自己命名的标识符的含义。我忘了。检查是否有哑音错误,然后继续前进。