ios 如何阻止 UITableView 单元格覆盖内容?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9794750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:25:59  来源:igfitidea点击:

How to stop UITableView cell is overwriting the contents?

iosobjective-cuitableviewtableviewcellcustom-cell

提问by zardon

I am using a UITableView and I'm noticing that the cells in my tableview are getting progresively bolder as I scroll, it is overwriting the contents and I want to stop this but can't see where I'm going wrong.

我正在使用 UITableView 并且我注意到我的 tableview 中的单元格在我滚动时变得越来越粗,它正在覆盖内容,我想停止它,但看不出哪里出错了。

On my UITableView, for some reason when I scroll the contents of the tableview get messed up with the the manually created UILabel.

在我的 UITableView 上,由于某种原因,当我滚动 tableview 的内容时,会与手动创建的 UILabel 混淆。

I require a manual UILabel because I need to have custom cells later on.

我需要手动 UILabel 因为我稍后需要自定义单元格。

As I scroll up and down, the labels get progressively bolder and bolder; they always overlap and sometimes even affects rows lower down (even before they are in the viewport).

当我上下滚动时,标签变得越来越粗;它们总是重叠,有时甚至会影响较低的行(甚至在它们进入视口之前)。

If I keep doing it, the cell contents become unintelligable.

如果我继续这样做,单元格内容就会变得难以理解。

This only happens if there the backgroundColor is not set as clearColor.

仅当 backgroundColor 未设置为 时才会发生这种情况clearColor

I have attempted [cellLabel setClearsContextBeforeDrawing:YES];and [self.tableView setClearsContextBeforeDrawing:YES];to no effect.

我已经尝试过[cellLabel setClearsContextBeforeDrawing:YES];,但[self.tableView setClearsContextBeforeDrawing:YES];没有效果。

If I use cell.textLabel.textthen the problem seems to go away.

如果我使用,cell.textLabel.text那么问题似乎消失了。

Code and an image sample follows.

代码和图像示例如下。

  // Simple table view
    - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    {
        static NSString *CellIdentifier = @"Cell";

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

        // Configure the cell...
        //[self configureCell:cell atIndexPath:indexPath];


        NSString *txt = @"Product";


        //cell.textLabel.text = txt;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        UIView *cellView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, cell.frame.size.height)];

        UILabel *cellLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 120, 35)];
        [cellLabel setText:txt];
        [cellLabel setFont:[UIFont boldSystemFontOfSize:12]];
        [cellLabel setBackgroundColor:[UIColor clearColor]];

        [cellView addSubview:cellLabel];
        [cellLabel release];
        [cell.contentView addSubview:cellView];
        [cellView release];


        return cell;
    }


Image follows;


![image of uitableview][1]


  [1]: http://i.stack.imgur.com/5lNy6.png


// Edit to include context

I am using a dictionary to display the contents of the UITableViewCells.

I have attempted to do the following;

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

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

            [self configureCell:cell atIndexPath:indexPath];
        } // end if


        // Configure the cell...
        //
       // Moved to inside the cell==nil        

        return cell;
    }

-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{

    // Get the txt from the Dictionary/Plist... *removed due verboseness*

    UILabel *cellLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 120, 35)];
    [cellLabel setText:txt];
    [cellLabel setFont:[UIFont boldSystemFontOfSize:12]];
    [cellLabel setBackgroundColor:[UIColor clearColor]];

    [cell.contentView addSubview:cellLabel];
    [cellLabel release];
}

This, although it fixes the problem of overwriting -- it causes a problem -- it makes labels repeatedly appear in totally random places -- the following is just an example, other fields and labels also repeat.

这个,虽然它解决了覆盖的问题——它导致了一个问题——它使标签重复出现在完全随机的地方——以下只是一个例子,其他字段和标签也重复。

See picture below;

见下图;

repeating labels in uitableview

在uitableview中重复标签

回答by A-Live

    // cell reuse
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

returned you the cell already been used, it already has an UILabel subview and you are adding another over it. Put the adding subviews at the section

返回给你已经使用过的单元格,它已经有一个 UILabel 子视图,你正在添加另一个子视图。将添加子视图放在该部分

   if (cell == nil) { //cell initialization

and edit the subviews as needed afterthe cell initialization, you can access them by tag for example.

并在单元格初始化根据需要编辑子视图,例如您可以通过标签访问它们。

回答by felbus

You are adding the label to the same reused cell every time, that is why it is getting bolder. When you use dequeueReusableCellWithIdentifier, you are grabbing a cell that has already been displayed on the screen, which is the correct thing to do, but you have already put a label on it. As the label will be in the same position relative to the cell each time, and the same color etc.. (the only dynamic element will be the text), you should set all this up only once.

您每次都将标签添加到同一个重复使用的单元格中,这就是它变得更大胆的原因。当您使用dequeueReusableCellWithIdentifier,你抓住那已经显示在屏幕上,这是应该做的正确的事情上的单元格,但你已经把一个标签就可以了。由于标签每次都相对于单元格位于相同的位置,并且具有相同的颜色等(唯一的动态元素将是文本),因此您应该只设置一次。

My preferred solution is to create a custom cell with the properties that you want. So in this case, you would create

我的首选解决方案是创建一个具有所需属性的自定义单元格。因此,在这种情况下,您将创建

@interfacce MyCustomCell : UITableViewCell
    @property (nonatomic) UILabel *cellLabel;
@end

Give it a property UILabel *cellLabel, and do all the code you have above apart from setting the labels text in the init of MyCustomCell.m, replace any instances of cell with self, for example:

给它一个属性 UILabel *cellLabel,除了在 MyCustomCell.m 的 init 中设置标签文本外,执行上面所有的代码,用 self 替换任何单元格实例,例如:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self)
    {
        self.cellLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 120, 35)];
        [self.cellLabel setText:txt];
        [self.cellLabel setFont:[UIFont boldSystemFontOfSize:12]];
        [self.cellLabel setBackgroundColor:[UIColor clearColor]];
    }

    return self;
}

Now in your cellForRowAtIndexPath use MyCustomCell, where you check if cell == nil, you might want to also check the cell label:

现在在您的 cellForRowAtIndexPath 中使用 MyCustomCell,您可以在其中检查 cell == nil,您可能还想检查单元格标签:

if(cell == nil || cell.cellLabel == nil)

Initialise it in exactly the same way:

以完全相同的方式初始化它:

cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

now, all you need to do is set:

现在,您需要做的就是设置:

cell.cellLabel.text = ....;

your code in cellForRowAtIndexPath is a lot cleaner, memory efficient and and you will not get your bug.

您在 cellForRowAtIndexPath 中的代码更干净,内存效率更高,并且您不会遇到错误。

Remember to set your cell to be of type MyCustomCell in interface builder.

请记住在界面构建器中将您的单元格设置为 MyCustomCell 类型。

回答by ramgandhi

This is a bit older thread. But will be useful to someone,

这是一个有点旧的线程。但对某人有用,

You can remove any viewadded to a cellbefore the same being reused in the tableView.

您可以删除任何view添加到cell同一作为一个在重新使用之前tableView

This code will do that,

这段代码会做到这一点,

for (UIView* view in [cell.contentView subviews])
{
    if ([view isKindOfClass:[UILabel class]])  //Condition if that view belongs to any specific class       
    {
        [view removeFromSuperview];
    }
}

This can be added before configuring the cell,

这可以在配置单元之前添加,

if (!cell) {
    cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier];

} 

You can also make cell's label values to nil to avoid repetition in trailing cells.

您还可以将单元格的标签值设为 nil 以避免在尾随单元格中重复。

cell.textLabel.text = nil;
cell.detailTextLabel.text = nil;
cell.textLabel.font = nil;

回答by jayesh kavathiya

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

           UITableViewCell *cell = (UITableViewCell*)[self.YourTableName dequeueReusableCellWithIdentifier:nil];        
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
        }


            return cell; 
        }

use ReusablecellIdentifier nil so it working correctly.....

使用 ReusablecellIdentifier nil 使其正常工作.....

回答by Anuj Kumar Rai

Write this code for collectionView. It will help to remove duplicity from reusable cell.

为 collectionView 编写此代码。这将有助于消除可重复使用单元的重复性。

- (void)viewDidLoad {
[super viewDidLoad];
arrImg=[[NSMutableArray alloc]initWithObjects:@"images.jpeg",@"images-2.jpeg",@"images-3.jpeg", nil];

UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setItemSize:CGSizeMake(375, 200)];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];

[self.colView setCollectionViewLayout:flowLayout];
self.colView.backgroundColor=[UIColor lightGrayColor];
self.colView.delegate=self;
self.colView.dataSource=self;

// Do any additional setup after loading the view, typically from a nib.
 }

  -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {


CollectionViewCell1 *cell=(CollectionViewCell1 *)[colView dequeueReusableCellWithReuseIdentifier:@"CollectionViewCell1" forIndexPath:indexPath];
float xAxis=0;
float maxwidth=0;


for (UIView* view in [cell.contentView subviews])
{
    if ([view isKindOfClass:[UIScrollView class]])  //Condition if that view belongs to any specific class
    {
        [view removeFromSuperview];
    }
}
if(indexPath.row==1)
{
    UIScrollView *scroll=[[UIScrollView alloc]initWithFrame:CGRectMake(0,0, colView.frame.size.width, 200)];

    scroll.delegate = self;
    [cell.contentView addSubview:scroll];

    for(int i=0;i<[arrImg count];i++)
    {

    UIImageView *img=[[UIImageView alloc]init];
    xAxis=xAxis+maxwidth;
    img.frame=CGRectMake(xAxis, 0, self.view.frame.size.width, 200);
    img.image=[UIImage imageNamed:[NSString stringWithFormat:@"%@",[arrImg objectAtIndex:i]]];
        [scroll addSubview:img];
        maxwidth=self.view.frame.size.width;
    }

   scroll.contentSize=CGSizeMake(375*3, 200);
   scroll.pagingEnabled=YES;


}
   return cell;

}

回答by Lolloz89

Try to not put the UIView *cellView over the UITableViewCell *cell. The UITableViewCell is a subclass of an UIView so you can add subviews if you want. However UITableViewCell has already a label inside.

尽量不要将 UIView *cellView 放在 UITableViewCell *cell 上。UITableViewCell 是 UIView 的子类,因此您可以根据需要添加子视图。但是 UITableViewCell 里面已经有一个标签了。

Just use [cell.textLabel setText:txt].

只需使用[cell.textLabel setText:txt].

回答by zardon

A-Live's answer was the best solution.

A-Live 的回答是最好的解决方案。

I found https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.htmlto give a much broader example.

我发现https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html给出了一个更广泛的例子。

However, in my experiments I was able to set up UITableViewCells that did not overwrite, and did not put cell values in random positions.

但是,在我的实验中,我能够设置不会覆盖的 UITableViewCells,并且不会将单元格值放在随机位置。

The code I used is below, it could do with tiyding up, but it seems to work for now;

我使用的代码在下面,它可以用来整理,但现在似乎可以工作;

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

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    UILabel *cellLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 120, 35)];
    [cellLabel setFont:[UIFont boldSystemFontOfSize:12]];
    [cellLabel setBackgroundColor:[UIColor clearColor]];
    [cellLabel setTag:1];
    [cell.contentView addSubview:cellLabel];
    [cellLabel release];




    // TextInput setup    
    CGRect cellTextFrame = CGRectMake(200, 12, 65, 30);


    UITextField *txtInputField = [[UITextField alloc] initWithFrame:cellTextFrame];
    [txtInputField setTag:2];
    [txtInputField setDelegate:self];
    [txtInputField setClearButtonMode:UITextFieldViewModeWhileEditing];
    [txtInputField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
    [txtInputField setFont:[UIFont systemFontOfSize:12]];
    [txtInputField setReturnKeyType:UIReturnKeyDone];
    [txtInputField setTextAlignment:UITextAlignmentLeft];
    [txtInputField setKeyboardAppearance:UIKeyboardAppearanceDefault];
    [txtInputField setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
    [txtInputField setAutocorrectionType:UITextAutocorrectionTypeNo];
    [txtInputField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
    txtInputField.clearButtonMode = UITextFieldViewModeWhileEditing;
    [txtInputField setBorderStyle:UITextBorderStyleRoundedRect];
    txtInputField.textColor = [UIColor colorWithRed:56.0f/255.0f green:84.0f/255.0f blue:135.0f/255.0f alpha:1.0f];
    //[txtInputField addTarget:self action:@selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit];     

    [cell.contentView addSubview:txtInputField];
    [txtInputField release];

} // end if


// Configure the cell...
//
//[self configureCell:cell atIndexPath:indexPath];


UILabel *label = (UILabel *)[cell viewWithTag:1];
[label setText:txt];

UITextField *txtField = (UITextField *) [cell viewWithTag:2];
[txtField setText:txtText];
[txtField setPlaceholder:txtPlaceholder];



return cell;