如何使具有不同子视图的UITableViewCell可重用?

Phl*_*bbo 5 iphone objective-c uitableview ios

我有一个UITableView我自然显示的,UITableViewCells它们都是同一个类,让我们称之为MyCell.所以我有一个MyCell.xib,一个MyCell.h和一个MyCell.m.

不幸的是,这个单元确实包含一个子视图,它包含不同的内容,例如a train subview和a car subview.因此,如果UITableView需要一个新的单元格,它总是一个MyCell但有时它包含一个火车子视图,有时还包含一个汽车子视图.

现在,这是我的问题:如何MyCell正确地重复使用?单元本身可以按预期重复使用(在.xib中我定义了它的标识符)但是必须为每个单元一次又一次地创建子视图.我的第一个想法是MyCell根据内容更改标识符,但遗憾的是,无法在运行时更改reuseIdentifier.但是,我可以实现我自己的- (NSString *) reuseIdentifier {}工作,但我不认为它很棒.有一个更好的方法吗?

提前谢谢了!

编辑:我意识到我需要添加子视图存储在他们自己的类/ xib中以保持他们的代码分离.

Nic*_*ver 11

我建议您为每种类型的单元格创建自己的类,而不是将子视图添加到单元格.如果您有各种类型:火车,汽车,自行车,船和飞机,我会创建五个子类.

据我了解Apple,带有标识符的重用机制仅适用于这种情况:不同类型的单元格获得自己的标识符,而不是每个单元格都是特殊的标识符.只是指出我如何解释整个事情.

在Apple的Table View编程指南(适用于iOS/Cell Objects的特性)中,第3个paragrpah可以深入了解重用标识符的含义.

我自己编写了一个小的TableViewCellFactory类,它使我的生活更容易使用界面构建器创建单元格,并在几分钟内将它们放在我的应用程序中.

首先是一个关于如何使用cellForRowAtIndexPath和工厂以及为单元格设置内容的小例子.

我用工厂创建了一个新的单元格,需要tableView,因此它可以处理重用逻辑.接下来就是让方法填写单元格的内容.在这种情况下,它是一个显示带有一些文本的视频剪辑的单元格.

数据源委托方法和帮助程序

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)anIndexPath
{
    VideoClipTableViewCell *cell = [TableViewCellFactory videoClipTableViewCellWithTableView:aTableView];

    [self configureVideoClipCellWithCell:cell andIndexPath:anIndexPath];

    // code to decide what kind of cell not shown, but it could be here, just move the model
    // access code from the configure cell up here and decide on what you get

    return cell;
}
Run Code Online (Sandbox Code Playgroud)

接下来是将内容放入单元格的数据源帮助程序.从我的模型数组中获取内容并设置属性.注意,这通过引用完成所有操作,不返回任何内容.

- (void)configureVideoClipCellWithCell:(VideoClipTableViewCell *)aCell andIndexPath:(NSIndexPath *)anIndexPath
{
    VideoClip *videoClip = [videoClips objectAtIndex:anIndexPath.row];

    aCell.videoTitleLabel.text = videoClip.title;
    aCell.dateLabel.text = videoClip.date;

    // more data setting ...
}
Run Code Online (Sandbox Code Playgroud)

TableViewFactory

该类主要包括方便方法和一些样板方法来完成实际工作.

// Convenience static method to create a VideoClipTableViewCell
+ (VideoClipTableViewCell *)videoClipTableViewCellWithTableView:(UITableView *)aTableView
{
    return [self loadCellWithName:@"VideoClipTableViewCell" tableView:aTableView];
}

// method to simplify cell loading
+ (id)loadCellWithName:(NSString *)aName tableView:(UITableView *)aTableView
{
    return [self loadCellWithName:aName 
                        className:aName
                       identifier:aName
                        tableView:aTableView];
}

// method with actually tries to create the cell
+ (id)loadCellWithName:(NSString *)aName 
             className:(NSString *)aClassName 
            identifier:(NSString *)anIdentifier 
             tableView:(UITableView *)aTableView
{
    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:anIdentifier];

    if (cell == nil) {
        UINib * nib = [UINib nibWithNibName:aName bundle:nil];  

        NSArray * nibContent = nil;

        nibContent = [nib instantiateWithOwner:nil options:nil];

        for (id item in nibContent) {
            if ([item isKindOfClass:NSClassFromString(aClassName)]) {
                cell = item;
            }
        }
    }
    return cell;
}
Run Code Online (Sandbox Code Playgroud)

我抛弃了整个错误和异常处理只是为了保持示例简短.如果有人有兴趣我会添加代码.

关于使用的一些重要事项是:

  • 连接的类名,重用标识符和nib名称都是相同的,因此只能使用一个字符串常量创建单元格,否则loadCellWithName必须使用long .

  • 不要忘记在界面构建器中设置重用标识符.

  • nib应该只包含一个TableViewCell(虽然可以通过一些编码进行更改)

  • 不要设置文件所有者的出口,使用tableViewCell的出口

  • 将单元格的类标识设置为应该首先创建的相应类

  • 看截图

在此输入图像描述

关于子类化自定义单元格的想法

实际上很容易将自己的单元格子类化,为它添加一些属性,使它们在带有出口的IB中可用,在IB中为您的nib文件选择新的扩展类.

主要问题是界面本身.基于接口构建器中的自定义单元格,使用不同类型的单元格并不容易.第一种方法是复制nib文件,重命名它并将其与所有现有引用一起使用,并将新文件链接到不同的出口.但是如果必须改变基本单元会发生什么?经历各种遗传细胞可能是一项繁琐的工作.

我只是在Cocoa with Love上使用IBPlugins在Interface Builder中偶然发现了自定义视图.这是一个很好的教程,如何在IB中扩展组件库.我们的自定义基本单元可以成为库中的项目,并成为我们一直在寻找的模板.我认为这种方法是正确的选择方式.不过,看看必要的步骤,它不仅仅是在5分钟内完成的.

界面构建器是一个有用的工具,允许我们快速创建视图,但是当涉及通过子类化的可重用性时,创建可维护视图需要很大的步骤.可惜.

仅使用代码创建视图我认为如果涉及多个继承级别或只有一个基本视图的许多祖先类,则子类化会更好.

编辑

另一方面,Apple警告过在单元格中过度使用子视图:

但是,如果单元格的内容由三个或四个以上的子视图组成,则滚动性能可能会受到影响.在这种情况下(特别是如果单元格不可编辑),请考虑直接在单元格内容视图的一个子视图中绘制.本指南的要点是,在实现自定义表格视图单元格时,请注意在最佳滚动性能与最佳编辑或重新排序性能之间存在权衡.

目前任何方法都有其缺点和优点:

  • 通过IB轻松完成太人的子视图将达到性能

  • 使用代码绘制将导致难以维护的代码库,但性能会更好

  • 跳过IB使得模板单元类的子类化更容易

  • 使用带有nib文件的IB难以实现子类化的层次结构