UITableView自定义单元格引发SIGABRT错误



我正在尝试为UITableView创建一个自定义单元格。我正在使用Xcode 4.2,并将故事板与ARC一起使用。

我创建了一个类来表示自定义单元格,如下所示:

结果CustomCell.h

#import <UIKit/UIKit.h>
@interface ResultsCustomCell : UITableViewCell
{
    IBOutlet UILabel *customLabel;
}
@property (nonatomic, retain) IBOutlet UILabel* customLabel;
@end

结果CustomCell.m

#import "ResultsCustomCell.h"
@implementation ResultsCustomCell
@synthesize customLabel;
@end

然后,我在视图控制器中实现了UITableView方法,如下所示:ViewController.m

#import "ViewController.h"
#import "ResultsCustomCell.h"
@implementation ViewController
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
    [super viewDidLoad];
}
// Set the number of items in the tableview to match the array count
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{   
    return 5;
}
// Populate TableView cells with contents of array.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";
    ResultsCustomCell *myCell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
    myCell.customLabel.text = @"helloWorld";
    return myCell;
}
// Define height for cell.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 80;
}
@end

应用程序成功构建,但随后立即崩溃,并给我以下错误:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

我遗漏了什么部分?

这是一个令人恼火的问题,因为调试器对发生的事情没有任何线索。如果单击"继续执行",它将在异常时中断,然后简单地关闭。

这让我抓狂了30分钟,直到我右键点击了自定义单元格中的一个UILabel,它给了我问题,这揭示了答案:你单元格中的某个控件有(或者有,正如你显然修复的那样,也许没有注意到)一个虚假的出口。所谓"虚假出口",我指的是连接到您的类中不再存在的IBOutlet属性的出口。在我的案例中,我更改了房产的名称并重新布线,但忘记删除旧的参考插座连接。

我一去掉那个令人反感的出口,问题就解决了。

当它没有退出队列时,您忘记创建新的UITableViewCell

// Populate TableView cells with contents of array.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";
    ResultsCustomCell *myCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (myCell == nil) {
        myCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    myCell.customLabel.text = @"helloWorld";
    return myCell;
}

您忘记在故事板中针对原型单元添加重用标识符("CellIdentifier"),因此当它尝试创建新单元时,故事板中没有具有该标识符的原型,并且它返回nil

@property (nonatomic, retain) IBOutlet UILabel* customLabel;

自动参考计数(ARC)禁止显式调用retain。请尝试删除此。

至于错误,您确实返回了UITableViewCell,而不是您的自定义单元格。此外,您从不分配ResultsCustomCell

- (ResultsCustomCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";
    ResultsCustomCell *cell = (ResultsCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[ResultsCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    // Configure the cell.
    cell.textLabel.text = @"Text";
    return cell;
}

此外,UITableViewCell的子类没有声明(显然是强制性的)方法init

结果CustomCell.h:

#import <UIKit/UIKit.h>
@interface ResultsCustomCell : UITableViewCell
@property (strong, nonatomic) UILabel *myLabel;
@end

结果CustomCell.m:

#import "ResultsCustomCell.h"
@implementation ResultsCustomCell
@synthesize myLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}
@end

编辑:我看到了,你正在使用故事板。我的建议可能对你有帮助,也可能对你没有帮助。我从来没有用过故事板。

我不完全确定我已经做了什么来解决我的问题,但它现在工作正常。

以下是我目前在ViewController.m 中的内容

注意:ResultsCustomCell.h和.m与上述内容相同。

#import "ViewController.h"
#import "ResultsCustomCell.h"
@implementation ViewController
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
    [super viewDidLoad];   
}
// Set the number of items in the tableview to match the array count
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{   
    return 5;
}
// Populate TableView cells with contents of array.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";
    // Make sure there are no quotations (") around the cell Identifier.
    ResultsCustomCell *myCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    myCell.customLabel.text = @"helloWorld";
    return myCell;
}
// Define height for cell.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 80;
}
@end

然后我确保以下内容正确无误:

  • 表视图单元格具有正确的自定义类(ResultsCustomCell)
  • UITableViewCell的单元格标识符在接口生成器中是正确的
  • 接口生成器中的UILabel已正确链接到IBOutlet
  • UITableView视图具有正确的控制器(ViewController)

使用此代码并检查以上所有内容后,它似乎可以工作。

我也在使用与您相同的设置来解决这个错误。我意识到,对我来说,这是由iOS6的新"自动布局"功能引起的。为了禁用它,我打开了自定义单元格xib,然后在右边的实用程序上打开了文件检查器选项卡(最左边的选项卡)。在那里我可以取消选中"使用自动布局"。

我错误地用错误的类类型注册了标识符,从而创建了此异常。

//The Identifier is register with the wrong class type
self.listView.register(CustomCellClass1.self, forCellReuseIdentifier: "CustomCellClass2")

然后退出队列并转换到不同的类类型:

let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCellClass2", for: indexPath) as! CustomCellClass2