29

我的UICollectionView. 最初它显示正常,显示一个单元格网格,每个单元格都有一个UIImageView. 这些UIImageViews显示了存储在应用程序包中的具有透明度的 PNG。

我的问题是,一旦UICollectionView滚动,某些单元格似乎已损坏。

损坏的单元格显示了多个堆叠在一起的图像,最上面的图像是它应该显示的图像,下面的图像是应该在其他单元格中使用的图像。

我最好的猜测是,这与 a 中的单元格UICollectionView被重用的方式有关,但我愿意接受建议。

这是我用于在以下范围内创建单元格的委托代码UICollectionView

// creates the individual cells to go in the menu view
- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    // create collection view cell
    UICollectionViewCell * cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];

    // create a uiview where we can place all views that need to go into this cell
    UIView * contents=[[UIView alloc] initWithFrame:cell.contentView.bounds];
    [contents setBackgroundColor:[UIColor clearColor]];
    [cell.contentView addSubview:contents];

    // add a button image
    NSString * buttonPath=[[NSBundle mainBundle] pathForResource:@"button" ofType:@"png" inDirectory:[[buttons objectAtIndex:indexPath.row] objectForKey:@"name"]];
    UIImage * button=[UIImage imageWithContentsOfFile:buttonPath];
    UIImageView * buttonView=[[UIImageView alloc] initWithImage:button];
    [buttonView setContentMode:UIViewContentModeScaleAspectFit];
    [buttonView setFrame:contents.bounds];
    [contents addSubview:buttonView];

    // set tag to the indexPath.row so we can access it later
    [cell setTag:indexPath.row];

    // add interactivity
    UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onButtonTapped:)];
    [tap setNumberOfTapsRequired:1];
    [cell addGestureRecognizer:tap];

    // return the cell
    return cell;

}

如果需要,我可以提供更多代码。

如何阻止细胞损坏?

4

7 回答 7

42

问题是您不断向 中添加视图,UICollectionViewCell因为UICollectionView. 所以旧UIImageView的 's 仍然在单元格上,因为您正在添加一个cellForItemAtIndexPath:被称为的。

不要使用addSubview:

相反,您可以创建一个自定义单元格,其中包含您想要的所有视图。因此,当cellForItemAtIndexPath:调用时,您只需要设置此 CustomCollectionViewCell 的内容即可。

这样它肯定会停止被破坏。


如何构建 CustomCell。

第1 步:创建 .h 和 .m 类。

自定义单元格.h

#import <UIKit/UIKit.h>

@interface CustomCell : UICollectionViewCell
{
    UIImageView *imageView;
}

@property (nonatomic, retain) UIImageView *imageView; //this imageview is the only thing we need right now.

@end

CustomCell.m

#import "CustomCell.h"

@implementation CustomCell

@synthesize imageView;

- (id)initWithFrame:(CGRect)aRect
{
    if (self = [super initWithFrame:aRect])
    {
         //we create the UIImageView in this overwritten init so that we always have it at hand.
         imageView = [UIImageView alloc] init];
         //set specs and special wants for the imageView here.
         [self addSubview:imageView]; //the only place we want to do this addSubview: is here!

         //You wanted the imageView to react to touches and gestures. We can do that here too.
         UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onButtonTapped:)];
        [tap setNumberOfTapsRequired:1];
        [self addGestureRecognizer:tap];


        //We can also prepare views with additional contents here!
        //just add more labels/views/whatever you want.
    }
    return self;
}

-(void)onButtonTapped:(id)sender
{
    //the response to the gesture.
    //mind that this is done in the cell. If you don't want things to happen from this cell.
    //then you can still activate this the way you did in your question.

}

第二步:导入!现在我们创建了 CustomCell,我们可以将它导入到我们想要使用它的类中。

第三步:在行动中使用它!

// creates the individual cells to go in the menu view
- (CustomCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    // create collection view cell
    CustomCell *cell = (CustomCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"CustomCell" forIndexPath:indexPath]; //this is the place where the CustomCell does his magic.
    //Make sure to use the CustomCellReuseId that you register in the viewdidload/loadview (step4)

    // add a button image
    NSString * buttonPath=[[NSBundle mainBundle] pathForResource:@"button" ofType:@"png" inDirectory:[[buttons objectAtIndex:indexPath.row] objectForKey:@"name"]];

    cell.imageView.image = [UIImage imageWithContentsOfFile:buttonPath]; //place the image on the CustemCell.imageView as we prepared.

    // set tag to the indexPath.row so we can access it later
    [cell setTag:indexPath.row]; //we don't need this to access the cell but I left this in for your personal want.

/*
 * we can now do this from the CustomCell as well!
 *
    // add interactivity
    UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onButtonTapped:)];
    [tap setNumberOfTapsRequired:1];
    [cell addGestureRecognizer:tap];
*/
    // return the cell
    return cell;

}

Step4:将单元格注册到collectionView

在 viewDidLoad / loadView 添加这一行:

[_collectionView registerClass:[CustomCell class] forCellWithReuseIdentifier:@"CustomCell"];

第五步:享受!您的 CustomCell 已完成。现在做任何你喜欢的事,别忘了也喝点咖啡。

于 2013-10-09T10:26:27.263 回答
6

紧接着

UICollectionViewCell * cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];

只需添加这一行,

[[[cell contentView] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
于 2014-12-08T05:52:02.040 回答
4

对于那些正在寻找 Swifty 答案的人,请将此函数添加到您的CustomCell课程中:

override func prepareForReuse() {
    contentView.subviews.forEach({ $0.removeFromSuperview() })
    // replace contentView with the superview of the repeating content.
}
于 2017-05-25T07:29:13.783 回答
3

发生这种情况是因为您每次都将 a 添加UIImageView到您的单元格以解决此问题,您必须制作一个自定义单元格,然后像使用它一样使用它:

自定义.h

#import <UIKit/UIKit.h>

@interface CustomCell : UICollectionViewCell

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

自定义.m

#import "CustomCell.h"

@implementation CustomCell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end

你的控制器

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

    CustomCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"CustomCell" forIndexPath:indexPath];

    NSString * buttonPath=[[NSBundle mainBundle] pathForResource:@"button" ofType:@"png" inDirectory:[[buttons objectAtIndex:indexPath.row] objectForKey:@"name"]];
    UIImage * button=[UIImage imageWithContentsOfFile:buttonPath];

    [cell.imageView setImage:button];

    return cell;
}

您还必须在 IB 中将“CustomCell”(如 Identifier)设置为单元格

于 2013-10-09T10:31:02.313 回答
1

这是为了从 uicollectionviewcell 的标签中删除重复的文本。

// Viewdidload
[_collectionView registerClass:[UICollectionviewcell class]     forCellWithReuseIdentifier:@"cellIdentifier"];



//in this method create label like this
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
  {
     UICollectionViewCell *cell=[collectionView   dequeueReusableCellWithReuseIdentifier:@"cellidentifier" forIndexPath:indexPath];
     for (UILabel *lbl in cell.contentView.subviews)
        {
            if ([lbl isKindOfClass:[UILabel class]])
            {
                [lbl removeFromSuperview];
            }
        }
     UILabel *nameLbl=[[UILabel alloc] initWithFrame:CGRectMake(0, 10, 50, 20)];
     nameLbl.text=[Array objectAtIndex:indexpath.row];                                                                                                                                  
     nameLbl.textColor=[UIColor whiteColor];
     [cell.contentView addSubview:nameLbl];
     return cell;

   }
于 2016-04-20T10:10:16.537 回答
0

对于以编程方式添加 UICollectionView 并拥有自定义单元格(即没有 XIB 文件)的任何人,您必须将此行添加到 viewDidLoad

[_collectionView registerClass:[CustomCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
于 2016-02-27T19:42:32.470 回答
-1
for (UIView *prevSubview in cell.contentView.subviews) {
    [prevSubview removeFromSuperview];
}
于 2015-10-25T23:52:20.020 回答