如何在同一个UITableView中正确显示不同的UITableViewCell子类?
我正在使用故事板来解决这个问题。我试图在一个表中使用两个不同的UITableView单元子类。 TTTextFieldCell
知道如何显示文本框和TTPickerCell
知道如何向用户呈现UIPicker的想法。协议TTTableViewCell
指定了一个选择器:[setCellDetails (NSDictionary*) cellDetails]
每个UITableViewCell
子类知道如何处理cellDetails字典来设置单元格。
-(NSArray *)tableData {
if (!_tableData) {
_tableData =
@[ // Sections
@{ // Section Details
kSectionName:@"Scout Information"
,kRows:@[ // Rows
@{// Cell Details
kBoundProperty:self.scoutName
,kReuseIdentifier:kTextFieldCell
,kLabel:@"Name"
,kPlaceholderValue:@"Scout's Name"
}
,@{
kReuseIdentifier:@"TTPickerCell"
,kLabel:@"Type"
,kPlaceholderValue:@"Cadet, Junior, etc..."
}
,@{
kBoundProperty:self.yearsScouting
,kReuseIdentifier:kTextFieldCell
,kLabel:@"Years"
,kPlaceholderValue:@"Years of Experience"
,kKeyboardStyle:@(UIKeyboardTypeNumberPad)
}
]
}
,@{ // Section Details
kSectionName:@"Parent Information"
,kRows:@[
@{
kBoundProperty:self.parentName
,kReuseIdentifier:kTextFieldCell
,kLabel:@"Name"
,kPlaceholderValue:@"Parents's Name"
}
]
}
];
}
return _tableData;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// Line A
[self.tableView registerClass:[TTTextFieldCell class] forCellReuseIdentifier:@"TTTextFieldCell"];
// Line B
[self.tableView registerClass:[TTPickerCell class] forCellReuseIdentifier:@"TTPickerCell"];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary* cellDetails = self.tableData[indexPath.section][kRows][indexPath.row];
NSString* reuseIdentifier = cellDetails[kReuseIdentifier];
// Line C
UITableViewCell<TTTableViewCell> *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
[cell setCellDetails:cellDetails];
return cell;
}
现在,问题就在这里。如果我注释掉A行和B行,则TTTextFieldCells会正确显示。但是C行会失败,因为它试图用TTPickerCell对象调用TTTextFieldCell init,并且由于TTPickerCell对象没有相同的属性而失败。如果我取消注释A行和B行,则单元格样式默认为UITableViewCellStyleDefault
,并且它们不显示自定义控件。奇怪的是,如果我注释掉A行,并取消注释B行,那么TTTextFieldCells
看起来很棒,但TTPickerCells
默认为UITableViewCellStyleDefault
。
似乎如果我没有注册一个类,dequeue将返回第一个原型单元类的实例。如果我注册该类,则单元格默认为UITableViewCellStyleDefault
。
另外值得注意的是,只有在注册类时才会调用initWithStyle:reuseIdentifier:selectors。
那么,如何在同一个UITableView中正确显示不同的UITableViewCell子类?我是否必须放弃使用故事板来设计单元格?
提前谢谢。
答案 0 :(得分:1)
您不希望在tableView registerClass:...
内拨打cellForRowAtIndexPath
。相反,您应该一次注册您的类/笔尖。这通常在控制器的viewDidLoad
方法中完成。您的cellForRowAtIndexPath
实现可能如下所示:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary* cellDetails = self.tableData[indexPath.section][kRows][indexPath.row];
NSString *reuseIdentifier = (/*some condition*/ ? @"TTTextFieldCell" : @"TTPickerCell");
UITableViewCell<TTTableViewCell> *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
[cell setCellDetails:cellDetails];
return cell;
}
编辑:我应该提到dequeueReusableCellWithIdentifier
总是从iOS 6返回一个单元格。如果你的目标是早期版本的iOS,你需要考虑创建单元格,即使这个方法返回nil。
答案 1 :(得分:0)
好的,这就是我发现的答案。
修正了#2,一切都很顺利。
卫生署!
答案 2 :(得分:-1)
我使用从NIB和NSMutable数组加载的两种类型的单元格与我的对象,对象具有我想在单元格中使用的文本,标题和图像。在方法cellForRowAtIndexPath ...中,将对象中的内容放入单元格。你可以在没有笔尖的情况下初始化。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (your condition){
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CellClass1" owner:self options:nil];
CellClass1 *cell = (CellClass1 *)[topLevelObjects objectAtIndex:0];
}else{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CellClass2" owner:self options:nil];
CellClass2 *cell = (CellClass2 *)[topLevelObjects objectAtIndex:0];}
//get your content for cell at array or your own estructure
Content *content = [contents objectAtIndex:indexPath.row];
cell.description.text = content.description;
return cell;
}