代码之家  ›  专栏  ›  技术社区  ›  Steven Fisher

复制UITableViewCell

  •  7
  • Steven Fisher  · 技术社区  · 15 年前

    我正在读取中的自定义表格单元格 tableView:cellForRowAtIndexPath: 从NIB文件。这对我来说很有用,只是速度很慢。

    现在,我知道从长远来看,正确的做法是完全用代码创建单元,并使用单一视图,等等。但这是一个原型,我不想投入那么多精力。

    现在,如果我只看一次笔尖,我会很高兴的。 UIViewController 然后,子类 表视图:cellForRowatindexPath: 复制了它。我的假设是,复制要比读笔尖快。

    这是我用来装笔尖的东西,我是从这里打电话来的 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 不支持复制协议。

    如果有必要的话,我可以告诉他们在我准备好完全移除笔尖之前不要考虑速度,但是如果这里有一个低悬的水果,我宁愿让它快点。

    有什么想法吗?

    5 回复  |  直到 8 年前
        1
  •  6
  •   Alex Wayne    15 年前

    使用表视图中内置的单元克隆。苹果知道产生大量的表格细胞是缓慢的。查看此方法的文档:

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

    创建一次单元,然后在请求新单元时,使用该方法克隆现有单元。然后您只需更改新单元格需要更改的内容,并返回单元格对象。

    还可以查看苹果公司提供的使用此方法的表视图实际示例代码,并向您展示正确的方法。你的手机是从笔尖上加载的,这一点也不重要。


    小说明:我不认为上面的方法为你克隆细胞。相反,它将从屏幕上滚动出来的单元格对象移动到一个新的点上。所以它实际上是在重复使用一个细胞。因此,请确保自定义表视图可以设置为除初始化之外所需的所有新值。

        2
  •  8
  •   Community kfsone    7 年前

    我认为表单元的应对可以与出列机制一起使用,出列机制允许创建一次单元(从NIB或以编程方式创建,或从其他NIB自动加载,并作为IB中的出口链接),然后在需要时克隆或出列。

    uiTableViewCell不符合nscopying协议,但它支持键控存档/无存档机制,因此可以用于克隆。

    基于答案” How to duplicate a UIButton in Objective C? “我的数据源委托方法如下:

    - (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.tableview单元格 是从视图的NIB文件加载一次的单元格。

    我没有测试什么会更快:“存档+无存档”来克隆或“加载NIB文件+无存档”,在这种情况下框架会做什么 -loadnibnamed:所有者:选项: ,我使用这种方法只是为了方便起见,但很有可能内存操作与文件操作会更快。

    编辑:看起来不像一开始那么容易。由于uiimage不符合nscoding,因此配置了uiimageview的单元格不能在没有附加代码的情况下复制。是的,复制整个图片绝对不是一个好的做法,为苹果公司指出这一点干杯。

        3
  •  4
  •   pfo    15 年前

    这一解决方案并不值得骄傲,但它可以使用尽可能多的ib绑定:

    接口(albumTableViewCell是在albumView控制器的XIB文件中定义实例的uiTableViewCell的子类):

    @interface AlbumsViewController : UITableViewController {
        IBOutlet AlbumTableViewCell *tableViewCellTrack;
    }
    
    @property (nonatomic, retain) AlbumTableViewCell *tableViewCellTrack;
    

    实现(unarchive/archive复制/克隆表视图单元):

    @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;
    }
    
        4
  •  3
  •   Teo Choong Ping    15 年前

    好吧,我不知道为什么所有的教程都没有指定这个步骤。

    从NIB使用自己的自定义UITableViewCell时,调用DequeueRusableCellWithIdentifier是不够的。您必须在ib中指定“标识符”,只需在表视图单元格选项卡部分中为其指定。

    然后确保您放入ib中的标识符与您用于dequeuersabellWithIdentifier的标识符相同。

        5
  •  1
  •   Joe C    9 年前

    这是斯威夫特的

    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!
    }