我正在尝试为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