如何清除caching的UITableViewCell

有没有人有关于如何清除caching的UITableViewCell

我想用reuseIdentifiercaching这些单元格。 不过,有时候我需要删除或修改一些表格行。 我希望行更改后调用reloadData

现在, dequeueReusableCellWithIdentifier总是返回之前的caching(过时)条目。 如何指示caching已过时并需要清除?

我不确定你为什么要首先清除细胞。 每次出队时,都需要重新设置需要显示的数据。 caching只是防止您每次都必须设置任何不变的属性。 但是,即使该单元格之前被caching,也必须设置显示的实际数据。

请注意,您的重用标识符应该是相同types的所有单元相同。 如果你正在做一些愚蠢的事情,比如根据所在行计算标识符,那么你做错了。

你的代码应该看起来像这样

 - (UITableViewCell *)tableView:(UITableView *)view cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     NSString * identifier = @“CellIdentifier”;

     UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if(!cell){
         //没有caching的单元格,在这里创build一个新的单元格
         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
         //设置所有这些单元格应共享的属性,如附件或文本颜色
     }
     //为这个特定的单元格设置数据
     cell.textLabel.text = @“foo”;
    返回小区;
 }

在这个例子中,请注意我每次如何总是为单元格设置数据,并且所有的单元格都共享相同的标识符。 如果你遵循这种模式,你应该没有任何理由试图“清除”你的单元格,因为任何旧数据都将被覆盖。 如果您有多种types的单元格,在这种情况下可能需要使用多个标识符,但每个单元格types仍有1个标识符。

我不知道如何清除caching,但是,我使用了一种解决方法,当需要更改行时,如何处理这种情况。

首先,我不使用静态单元标识符。 我要求数据对象生成它(注意[myObject signature] ,它提供了一个唯一的string描述所有需要的属性):

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { MyObject *myObject = _dataSource[indexPath.row]; NSString *cellId = [myObject signature]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; [myObject configureCell:cell]; } [myObject updateCellWithData:cell]; return cell; } 

[myObject signature]为不同的属性列表提供不同的签名。 所以,如果我的对象被改变,我只是调用[self.tableView reloadData] ,myObject将提供一个新的签名,并为它加载一个新的单元格。

[myObject configureCell:cell]将所有需要的子视图放到单元格中。

[myObject updateCellWithData:cell]用当前数据更新[myObject updateCellWithData:cell]的子视图。

 while ([tableView dequeueReusableCellWithIdentifier:@"reuseid"]) {} 

我find了一个非常好的方法。

在.h

 //add this int reloadCells; 

在.m

 - (void)dumpCache { reloadCells = 0; [tableView reloadData]; } -(void)tableView:(UITableView *)tableView cellForRowAtUndexPath:(NSIndexPath *)indexPath { static NSString *CellID = @"Cell" UITableViewCell *cell = [tableView dequeCellWithReuseIdentifier:CellID]; if (cell == nil || reloadCells < 12) { cell = [[UITableViewCell alloc] initWithFormat:UITableViewCellStyleDefault reuseIdentifier:CellID]; reloadCells ++; } cell.textLabel.text = @"My Cell"; return cell; } 

今天我有类似的东西。 我有一个图像库,当用户全部删除它时,库需要摆脱最后排队的单元格,并用“库空”图像replace它。 当删除例程完成时,它将“清除”标志设置为YES,然后执行[tableView reloadData]。 cellForRowAtIndexPath中的代码如下所示:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath NSString *cellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier]; if (purge) { cell = nil; purge = NO; } if (cell == nil) { //*** Do usual cell stuff } return cell } 

应该用消息prepareForReuse清除以前使用单元的旧数据。 当一个信元出队时,这个信息在从dequeueReusableCellWithIdentifier:返回之前被发送给信元。

没办法,我想…我用了一个完全不同的方法。 而不是依靠UITableViewcaching,我build立自己的。 通过这种方式,我可以完全控制什么时候清洗。 像这样的东西…

给定:

 NSMutableDictionary *_reusableCells; _reusableCells = [NSMutableDictionary dictionary]; 

我可以:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *cellIdentifier = @"whatever-you-need"; UITableViewCell *cell = [_reusableCells objectForKey:cellIdentifier]; if (cell == nil) { // create a new cell WITHOUT reuse-identifier !! cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; // store it in my own cache [_reusableCells setObject:cell forKey:cellIdentifier]; /* ...configure the cell... */ } return cell; } 

和:

 -(void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. [_reusableCells removeAllObjects]; } 

希望这可能有帮助。

我正在编写ObjC(手动引用计数),发现一些奇怪的行为,防止UITableView和UITableViewCells获得释放,虽然我的内存pipe理是正确的。 UITableView和UITableViewCell似乎保留对方。 是的,我find了一种方法来强制UITableView及其单元彼此释放(删除caching单元格)。

要做到这一点,基本上你要问一个可重用的单元格的表视图。 表视图将从可重用的单元格caching中删除它。 毕竟,你告诉该单元格从其超级视图中删除。 完成。

现在作为一个独立的类…首先,你需要一个你使用的所有单元格标识符的数组。 接下来,您实现一个虚拟数据源,并让该数据源通过使用“ClearAllCachedCells”数据源重新加载自身来清除UITableView:

 #import <UIKit/UIKit.h> @interface ClearAllCachedUITableViewCellsDataSource : NSObject <UITableViewDataSource, UITableViewDelegate> +(void)clearTableView:(UITableView*)tv reuseIdentifiers:(NSArray<NSString*>*)cellIdentifiers delegateAfterFinish:(id<UITableViewDelegate>)dg dataSourceAfterFinish:(id<UITableViewDataSource>)ds; @end 

而.m文件中发生的奇迹是:

 #import "ClearAllCachedUITableViewCellsDataSource.h" @interface ClearAllCachedUITableViewCellsDataSource () { BOOL clearing; } @property (nonatomic, readonly) UITableView *tv; @property (nonatomic, readonly) NSArray<NSString*> *identifiers; @property (nonatomic, readonly) id ds; @property (nonatomic, readonly) id dg; @end @implementation ClearAllCachedUITableViewCellsDataSource -(void)dealloc { NSLog(@"ClearAllCachedUITableViewCellsDataSource (%i) finished", (int)_tv); [_tv release]; [_ds release]; [_dg release]; [_identifiers release]; [super dealloc]; } -(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section { [self performSelectorOnMainThread:@selector(clear) withObject:nil waitUntilDone:NO]; NSLog(@"TV (%i): reloading with zero cells", (int)_tv); return 0; } -(void)clear { if (!clearing) { clearing = YES; for (NSString *ident in self.identifiers) { UITableViewCell *cell = [_tv dequeueReusableCellWithIdentifier:ident]; while (cell) { NSLog(@"TV (%i): removing cached cell %@/%i", (int)_tv, ident, (int)cell); [cell removeFromSuperview]; cell = [_tv dequeueReusableCellWithIdentifier:ident]; } } self.tv.delegate = self.tv.delegate == self ? self.dg : self.tv.delegate; self.tv.dataSource = self.tv.dataSource == self ? self.ds : self.tv.dataSource; [self release]; } } +(void)clearTableView:(UITableView*)tv reuseIdentifiers:(NSArray<NSString*>*)cellIdentifiers delegateAfterFinish:(id<UITableViewDelegate>)dg dataSourceAfterFinish:(id<UITableViewDataSource>)ds { if (tv && cellIdentifiers) { NSLog(@"TV (%i): adding request to clear table view", (int)tv); ClearAllCachedUITableViewCellsDataSource *cds = [ClearAllCachedUITableViewCellsDataSource new]; cds->_identifiers = [cellIdentifiers retain]; cds->_dg = [dg retain]; cds->_ds = [ds retain]; cds->_tv = [tv retain]; cds->clearing = NO; tv.dataSource = cds; tv.delegate = cds; [tv performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; } } @end