代码之家  ›  专栏  ›  技术社区  ›  ManniAT

清除TableView单元缓存(或删除条目)

  •  1
  • ManniAT  · 技术社区  · 15 年前

    我有和这里描述的一样的问题 How to purge a cached UITableViewCell

    但我的问题不能用“重置内容”来解决。

    准确地说,我使用自定义单元(自己的类)。运行应用程序时,可能需要使用不同的“单元类型”。 它是同一个类——但是它有(很多)不同的属性。 当然,我可以在“PrepareForReuse”中重置所有的东西,但我想这不是一个好主意(有很多东西需要重置)。

    我的想法-我在单元的构造器中做所有这些事情。 所有的行稍后都将使用这个“单元类型”。 当(很少)的情况发生时,我必须更改所有行的外观,我创建了一个具有不同设置的此类单元格的新实例。 现在,我想用这个新的单元替换排队的单元。

    我尝试简单地用相同的cellIdentifier调用构造函数(希望它能替换现有的),但这行不通。

    我也没有找到“透明纸盒子”或类似的东西。

    是否有清除缓存或删除/替换特定项的方法?

    曼弗雷德

    2 回复  |  直到 15 年前
        1
  •  2
  •   Steven Canfield    15 年前

    使用不同的标识符创建每个单元类型(即使它们使用相同的单元类)。因此,如果您有两个单元格类型,请定义两个标识符并将它们分开。

    我不知道你的问题在哪里。你有一堆细胞,有外观A,然后用户采取一些行动,他们需要成为外观B。如果你调用 reloadData 或者更精细的方法之一,将为CellForRowatindexPath再次调用数据源。只需实现此方法来分离这两种单元类型。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        NSString* identifier = which mode are we in
        UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier]; // Will return nil if we haven't got this cell
        if( !cell ) {
            // Create different cell type based on the identifier   
        }
        return cell;
    }
    
        2
  •  0
  •   Rich Waters    10 年前

    更新

    这不管用。从dequeueusablecellWithIdentifier返回的单元内存永远不会释放。

    如果使用非nil ReuseIdentifier初始化单元格,则在释放TableView本身之前,不会释放该单元格。即使调用了[[TableView ValueForkey:@“ReusableTableCells”]RemoveAllobjects],也是如此。不幸的是,TableView将单元保留在其他私有成员中,唯一释放单元的方法是销毁TableView。

    简短的回答

    如何清除TableView单元缓存这个问题的标题的答案是,Apple不提供“ClearReusableCells”功能,但是它相当容易实现自己。只需跟踪上次清除TableView缓存的时间,并跟踪创建单元格的时间。如果单元格是在TableView上次缓存刷新时间之前创建的,则该单元格被认为是脏的。

    选择

    • Steven Canfield的答案-这是对特定问题的一个很好的答案,但是如果有多个属性可以独立地相互更改,那么它就不能很好地扩展。在这种情况下,您可以非常迅速地拥有许多“模式”,并且这些模式会变得无法管理。此外,在内存使用方面,苹果代码确实负责管理内存,但库也无法知道何时可能再次需要某个特定的标识符,因此最终可能会使这些缓存的单元保持比需要的时间长一些。

    • 重新创建TableView——这是一种强力机制,可以保证清除单元缓存。不幸的是,重新创建TableView通常不方便。

    • Jake的Dahl回答了另一个问题——这是一个很好的清除缓存的机制,可能在写缓存时起作用,但它依赖于一些苹果不保证的实现,事实上,这些实现已经改变了。

    实施 有多种方法可以跟踪TableView的缓存刷新时间和单元创建时间。我在下面展示了一种使用子类的机制。当然,要使其工作,您需要确保实例化表和单元格的代码实例化子类。

    @interface MyTableView : UITableView
    @property(nonatomic,assign) NSTimeInterval cellCacheRefreshTime ;
    @end
    
    @interface MyTableViewCell : UITableViewCell
    @property(nonatomic,assign) NSTimeInterval creationTime ;
    @end
    
    
    @implemetation MyTableView
    
    -(void) refreshCellCache {
        self.cellCacheRefreshTime = [NSDate timeIntervalSinceReferenceDate];
    }
    
    - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier {
        MyTableViewCell *cell = (id)[super dequeueReusableCellWithIdentifier:identifier] ;
        if( cell.creationTime < aTableView.cellCacheRefreshTime ) {
            return nil ; 
        }    
        return cell ; 
    }
    
    @end
    
    
    @implemetation MyTableViewCell
    
    -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier] ;
        self.creationTime = [NSDate timeIntervalSinceReferenceDate];
        return self ;
    }
    
    @end