在使用 iOS6时设置 UITableViewCell 的样式:

我正在尝试解决如何设置的 UITableViewCellStyle时,使用新的方法在 iOS6的 UITableView

以前,在创建 UITableViewCell时,我会更改 UITableViewCellStyle枚举,以便在调用 initWithStyle:时创建不同类型的默认单元格,但从我收集到的信息来看,情况已经不是这样了。

苹果公司为 UITableView提供的文件中写道:

返回值 : 具有相关重用标识符的 UITableViewCell 对象。此方法始终返回有效的单元格。

讨论 : 出于性能原因,当表视图为其 tableView: cellForRowAtIndexPath: 方法中的行分配单元格时,表视图的数据源通常应该重用 UITableViewCell 对象。表视图维护数据源标记为重用的 UITableViewCell 对象的队列或列表。当被要求为表视图提供新单元格时,从数据源对象调用此方法。如果现有单元格可用,则此方法将其排队,或者基于先前注册的类或 nib 文件创建一个新单元格。

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

如果为指定的标识符注册了一个类并且必须创建一个新单元格,则此方法通过调用其 initWithStyle: reuseIdentifier: method 来初始化该单元格。对于基于 nib 的单元格,此方法从提供的 nib 文件加载单元格对象。如果现有单元可以重用,则此方法将调用该单元的 prareForReuse 方法。

这是我的新 cellForRowAtIndexPath在实现新方法之后的样子:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"cell_identifier";


[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellIdentifier];


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];


return cell;
}

到目前为止,我的代码工作得很好,但总是返回默认样式。我如何改变这一点,以便我可以创建与其他样式的细胞,如 UITableViewCellStyleDefaultUITableViewCellStyleValue1UITableViewCellStyleValue2UITableViewCellStyleSubtitle

我不想子类 UITableViewCell,我只是想改变默认类型,就像我在 iOS6之前可以做的那样。看起来很奇怪,苹果公司提供了增强的方法,但是只有很少的文档来支持它们的实现。

有没有人掌握了这一点,或遇到了类似的问题? 我正在努力寻找任何合理的信息在所有。

48377 次浏览

我知道你说过你不想创建一个子类但这看起来是不可避免的。基于在 iOS 6.0模拟器中测试时的汇编代码,UITableView通过执行以下命令创建 UITableViewCell(或其子类)的新实例

[[<RegisteredClass> alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:<ReuseIdentifier>]

换句话说,发送的样式(UITableViewCellStyleDefault)似乎是硬编码的。为了解决这个问题,您需要创建一个子类来覆盖默认的初始化器 initWithStyle:reuseIdentifier:,并传递您希望使用的样式:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
// ignore the style argument, use our own to override
self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier];
if (self) {
// If you need any further customization
}
return self;
}

此外,最好在 viewDidLoad中发送 registerClass:forCellReuseIdentifier:,而不是每次请求一个单元时都这样做:

- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:<RegisteredClass> forCellReuseIdentifier:<ReuseIdentifier>];
}

dequeueReusableCellWithIdentifier没有被弃用,所以不需要使用新的 dequeueReusableCellWithIdentifier:forIndexPath:

如果使用自定义单元格类,则使用新方法和适当的 register 方法(在 viewDidLoad 中) ,但如果希望使用 UITableViewCellStyle 枚举之一,则使用旧方法。

你可以通过使用故事板 Interface Builder 来避免无关的子类:

  1. 在 Storyboard 视图中,选择表视图单元格原型单元格(在表视图中)
  2. 在“实用工具”视图中的“属性”检查器中,修改“样式”值
  3. (可选)修改其他值,如选择和附件

新的 iOS 6.0 dequeueReusableCellWithIdentifier:forIndexPath:在分配新单元并返回它们时确实使用了这些值。(使用 Xcode 4.5.2在 iOS 6.0编译器上进行测试)

另一种保存一个文件的方法是创建一个 Nib 并使用 registerNib:forCellReuseIdentifier:

制作笔尖很容易: 创建一个新的。Interface Builder 中的 xib 文件。删除默认视图。添加表格视图单元格对象。使用“属性检查器”更改单元格的样式。(在这里,您还有机会通过调整其他属性进一步定制单元格。)

然后在表视图控制器的 viewDidLoad方法中调用类似于:

[self.tableView registerNib:[UINib nibWithNibName:@"StyleSubtitleTableCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"Cell"];

我的解决方案是在使用 [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]获得 initWithStyle: reuseIdentifier:之后调用它。毕竟,init只是另一个选择器,编译器对已经初始化的对象调用它没有限制。然而,它会抱怨没有使用 init 调用的结果,所以我这样做了:

UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath];
cell = [cell initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellId"];

我想这招在斯威夫特身上不管用。

Bolot 的答案是正确的。简单,不需要创建任何 XIB 文件。

我只是想更新一下他的回答,不管是谁在用 Swift 而不是 Objective-C 做这件事:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .value1, reuseIdentifier: reuseIdentifier)
}


required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}