滚动时 UITableView 中的数据重复

Posted

技术标签:

【中文标题】滚动时 UITableView 中的数据重复【英文标题】:Data repeat in UITableView when scrolling 【发布时间】:2013-07-04 10:09:26 【问题描述】:

我使用下面的代码在 TableView 上显示数据,但是在滚动时,数据重复和其他数据丢失。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return 1;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return [FileCompletedArray count];


cellForRowatindexpath():

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    static NSString *CellIdentifier = @"CellIdentifier";

    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        UILabel *FileNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 100, 30)];
        FileNameLabel.backgroundColor = [UIColor clearColor];
        FileNameLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
        FileNameLabel.font = [UIFont boldSystemFontOfSize:16];
        FileNameLabel.textColor = [UIColor blackColor];
        NSLog(@"Reseversed TEMP array %@",FileCompletedArray);
        FileNameLabel.text =[FileCompletedArray objectAtIndex:indexPath.row];
        [cell.contentView addSubview: FileNameLabel];
        [FileNameLabel release];



    
        return cell;

你有什么解决办法吗?提前致谢

【问题讨论】:

【参考方案1】:

使用不同的单元格标识符

例如像下面这样...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    NSString *CellIdentifier = [NSString stringWithFormat:@"%d,%d",indexPath.section,indexPath.row];

    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        /// write your code here..
    

OR 设置nil 如下所示..

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    //static NSString *CellIdentifier = @"CellIdentifier";    

    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:nil];
    if (cell == nil)
    
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
        /// write your code here..
    

【讨论】:

虽然这是解决方案之一,但我认为cell 不会被这段代码重用。每次它都会创建一个新的cell 这段代码不会重复使用单元格,而是每次都创建新的单元格。如果数据源很大,这将产生性能问题。此外,不重用单元格也不是一个好的编码习惯。 不,这不是问题,当您有大量数据时,您可以使用客户单元的可重用性.. :) 这段代码使单元格重用变得不可能。这是错误的。没有人嫉妒…… @vikingosegundo no mate 不仅因为这个答案,而且在我给出答案之后的某个时候,有人无缘无故地对我投了反对票.. 同样在这里你是对的,对于许多记录这种方法不好但是为此,我使用我的一种自定义方法来克服这个问题。如果出现问题,我会发布 Mate .. :)【参考方案2】:

这个问题是因为你的UITableView Reuse Cell 瞬间创建新的。 我给你一些建议,可能对你有帮助。

1) 在两者之间添加Controller

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath   
  
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    
        /// Your code of initialization of controller;
    

    /// set property of controllers such like (Text UILabel, image of UIImageView...etc) .
 return cell;


1) 将您的Controller 添加到cell.contentView.

已编辑:

在您关注我的编辑答案之前,我想告诉您以下代码不利于内存管理,因为它会为UITableView 的每一行创建新单元格,所以要小心。

但是如果UITableView有限制行大约(50-100 可能是)os 使用以下代码,如果它适合您,则更好。

NSString *CellIdentifier = [NSString stringWithFormat:@"S%1dR%1d",indexPath.section,indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil)
    
          /// Your whole code of controllers;
     

【讨论】:

【参考方案3】:

您仅在创建新单元格时设置标签的文本。但是,在单元重用期间,不会创建新单元。因此,您设置/更改文本的代码不起作用。您可以使用此修改后的代码。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    static NSString *CellIdentifier = @"CellIdentifier";

    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UILabel *FileNameLabel=nil;
    if (cell == nil)
    
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        FileNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 100, 30)];
        FileNameLabel.tag = 1001;
        FileNameLabel.backgroundColor = [UIColor clearColor];
        FileNameLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
        FileNameLabel.font = [UIFont boldSystemFontOfSize:16];
        FileNameLabel.textColor = [UIColor blackColor];
        [cell.contentView addSubview: FileNameLabel];
        [FileNameLabel release];
    
    if(!FileNameLabel)
        FileNameLabel = [cell.contentView viewWithTag:1001];
    FileNameLabel.text =[FileCompletedArray objectAtIndex:indexPath.row];

    return cell;

您也可以使用默认的textLabel 而不是创建和添加新标签

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    static NSString *CellIdentifier = @"CellIdentifier";

    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UILabel *FileNameLabel=nil;
    if (cell == nil)
    
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
        cell.textLabel.font = [UIFont boldSystemFontOfSize:16];
        cell.textLabel.textColor = [UIColor blackColor];
    
    cell.textLabel.text =[FileCompletedArray objectAtIndex:indexPath.row];

    return cell;

【讨论】:

【参考方案4】:

我也遇到了同样的问题,当我们重用单元格时会出现问题。在重用数据时,其中已经存在数据,我们还编写了更多数据,为了解决这个问题,我对我的表视图委托方法 cellForRowAtIndexPath 做了一个小的改动。这里我使用的代码总是使用表格视图。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) 
    cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];

for (UIView *view in cell.contentView.subviews) 
    [view removeFromSuperview];


return cell;

for 循环在我们重用某个单元格时执行,它的作用是删除 UITableViewCell 中存在的所有先前数据

希望这会对某人有所帮助。

【讨论】:

以上是关于滚动时 UITableView 中的数据重复的主要内容,如果未能解决你的问题,请参考以下文章

未分配给父 UIViewController 视图属性时,UITableView 不滚动

使用自定义子视图滚动 UITableView 时重复数据

在 UITableView 内时 UITextField 中的文本重复

iPhone通过滑出表格视图来滚动UITableview

滚动时tableview数据重复

iOS - UITableView - 快速滚动时神秘地重复自己的行? (模拟器)