English 中文(简体)
复制UITableViewCell
原标题:
  • 时间:2009-02-20 20:43:25
  •  标签:

我正在从nib文件读取自定义表格单元格,在 tableView:cellForRowAtIndexPath:中。除了它有些慢之外,这对我的目的非常有效。

现在,我知道从长远来看,正确的做法是完全使用代码创建单个视图等。但这只是一个原型,我不想花太多精力在上面。

现在,如果我在UIViewController子类中只读取nib一次,然后tableView:cellForRowAtIndexPath:创建副本,我会很高兴。我这里的假设是复制比读取nib要快。

这是我用来加载nib的方法,在viewDidLoad:中调用(并在之后retain)。

-(id)loadFromNamed:(NSString*)name {
    NSArray *objectsInNib = [[NSBundle mainBundle] loadNibNamed:name
                                                          owner:self
                                                        options:nil];
    assert( objectsInNib.count == 1 );
    return [objectsInNib objectAtIndex:0];
}

到目前为止一切都很好。但问题是:我如何复制这个来回复?这是否可能?

我尝试过使用 [_cachedObject copy][_cachedObject mutableCopy],但 UITableViewCell 不支持任何复制协议。

如果必要的话,我可以告诉他们在我准备完全拿掉笔尖之前忽略速度,但如果有简单的方法可以让它快一点的话,我宁愿去尝试。

有什么想法吗?

最佳回答

使用内置在表视图中的单元格克隆。 苹果公司知道生成大量表单元格很慢。 请查看此方法的文档:

- (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier

你只需创建一次细胞,然后在请求新细胞时,使用该方法克隆现有细胞。然后,您只需更改新细胞需要更改的部分并返回细胞对象。

同样请查看由苹果提供的相关使用此方法的表视图示例代码,并向你展示正确的方法。实际上,你的单元格是从XIB文件加载的,这并不重要。


小澄清:我认为上述方法并没有为您克隆单元格。相反,它将滚动出屏幕的单元格对象简单地移动到新位置。因此,它实际上是在重复使用单元格。因此,请确保您的自定义表视图可以在初始化之外设置所有需要的新值。

问题回答

我认为表格单元格的复制可以与排队机制一起使用,这将允许仅创建单元格一次(从nib或以编程方式或自动从其他nib加载并在IB中链接为输出),然后在需要时克隆或排队。

UITableViewCell不遵守NSCopying协议,但它支持键控编码/解码机制,因此它可以用于复制。

Based on answer " How to duplicate a UIButton in Objective C? " my data source delegate method looks like:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellID = @"CellIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID];

    if (!cell) {
        NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:self.tableViewCell];
        cell = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData];
    }

    // ... config ...

    return cell;
}

在我的情况下,self.tableViewCell 是从视图的nib文件加载一次的单元格。

我不知道哪种方法更快:“归档+解压缩”来克隆还是“加载nib文件+解压缩”在-loadNibNamed:owner:options:的情况下,我只考虑了方便性,但很有可能内存操作比文件操作更快。

编辑:一开始似乎并不容易。由于UIImage不符合NSCoding,带有配置UIImageView的单元格不能仅通过复制进行,需要额外的代码。是的,整个图像的复制绝对不是一个好习惯,对于苹果指出这一点而欢呼。

不为这个解决方案感到自豪,但它与最大数量的可能IB绑定一起工作。

接口(AlbumTableViewCell 是 UITableViewCell 的子类,其实例在 AlbumViewController 的 XIB 文件中定义):

@interface AlbumsViewController : UITableViewController {
    IBOutlet AlbumTableViewCell *tableViewCellTrack;
}

@property (nonatomic, retain) AlbumTableViewCell *tableViewCellTrack;

实现(取消存档/存档会创建一个副本/克隆表格视图单元格):

@implementation AlbumsViewController

@synthesize tableViewCellTrack;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    AlbumTableViewCell *cell = (AlbumTableViewCell *)[tableView dequeueReusableCellWithIdentifier: @"AlbumCell"];

    if (cell == nil) {
        AlbumsViewController *albumsViewController = [[[AlbumsViewController alloc] init] autorelease];
        [[NSBundle mainBundle] loadNibNamed: @"AlbumsViewController" owner: albumsViewController options: nil];

        cell = albumsViewController.tableViewCellTrack;
    }

    cell.labelTitle.text = ...;
    cell.labelArtist.text = ...;

    return cell;
}

嗯,我不确定为什么那里的所有教程都没有指明这一步骤。

当使用自己定制的 Nib UITableViewCell 时,仅调用 dequeueReusableCellWithIdentifier 是不够的。您还需要在 IB 中指定“Identifier”,只需找到“Table View Cell”选项卡中的该标识符。

然后请确保您在 IB 中输入的标识符与您用于 dequeueReusableCellWithIdentifier 的标识符相同。

这是用Swift编写的。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    var cell : UITableViewCell?
    let cellId = String(format: "Cell%d", indexPath.row)
    cell = alertTable!.dequeueReusableCellWithIdentifier(cellId) as! UITableViewCell?

    if cell == nil {
        let archivedData = NSKeyedArchiver.archivedDataWithRootObject(masterTableCell!)
        cell = NSKeyedUnarchiver.unarchiveObjectWithData(archivedData) as! UITableViewCell?
    }

    // do some stuff

    return cell!
}




相关问题
热门标签