82

我正在尝试解决如何UITableViewCellStyle在使用 iOS 6 中的新方法时设置UITableView.

以前,在创建 a 时,UITableViewCell我会更改UITableViewCellStyle枚举以在调用时创建不同类型的默认单元格,initWithStyle:但据我所知,情况不再如此。

UITableView用于状态的 Apple 文档:

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

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

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

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

这是实现新方法后我的新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;
}

到目前为止我的代码工作正常,但总是返回默认样式。如何更改此设置,以便创建具有其他样式的单元格,例如UITableViewCellStyleDefault、和?UITableViewCellStyleValue1UITableViewCellStyleValue2UITableViewCellStyleSubtitle

我不想子类UITableViewCell化,我只想像在 iOS 6 之前所做的那样更改默认类型。Apple 会提供增强的方法但用最少的文档来支持它们的实现似乎很奇怪。

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

4

6 回答 6

106

我知道您说过您不想创建子类,但这看起来是不可避免的。在 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;
}

此外,最好发送registerClass:forCellReuseIdentifier:in viewDidLoad,而不是每次请求单元格时都发送:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:<RegisteredClass> forCellReuseIdentifier:<ReuseIdentifier>];
}
于 2012-11-02T11:27:36.577 回答
61

dequeueReusableCellWithIdentifier不推荐使用,因此您不需要使用新的dequeueReusableCellWithIdentifier:forIndexPath:.

如果您使用自定义单元格类,请使用新方法和适当的注册方法(在 viewDidLoad 中),但如果您想使用 UITableViewCellStyle 枚举之一,请使用旧方法。

于 2012-11-22T17:21:18.117 回答
11

您可以使用故事板界面构建器来避免无关的子类:

  1. 在 Storyboard 视图中,选择 table view cell 原型单元格(在 table view 上)
  2. 在 Utilities 视图的 Attributes 检查器中,修改 Style 值
  3. (可选)修改其他值,例如 Selection 和 Accessory

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

于 2013-02-11T02:16:07.720 回答
7

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

制作 Nib 很简单:在 Interface Builder 中创建一个新的 .xib 文件。删除默认视图。添加一个表格视图单元格对象。使用属性检查器,更改单元格的样式。(在这里您还可以通过调整其他属性来进一步自定义单元格。)

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

[self.tableView registerNib:[UINib nibWithNibName:@"StyleSubtitleTableCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"Cell"];
于 2013-04-18T17:58:55.400 回答
0

博洛特的回答是正确的。简单,您不需要创建任何 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")
}
于 2017-12-15T14:40:26.020 回答
-5

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

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

我想这在 Swift 中行不通……

于 2015-06-11T08:17:40.940 回答