UICollectionViewCell 问题与 registerClass

UICollectionViewCell issues with registerClass

我正在尝试在不使用故事板或 nib 的情况下以编程方式创建集合视图单元格。

这是我的cell.h文件

#import <UIKit/UIKit.h>

@interface TestCVCell : UICollectionViewCell {
    UILabel *label;
}

@property (nonatomic, retain) UILabel *label;

@end

这是 .m 文件

#import "TestCVCell.h"

@implementation TestCVCell

@synthesize label;

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self) {
        if (!self.label) {
            label = [[UILabel alloc] initWithFrame:self.frame];
            label.textColor = [UIColor whiteColor];

            self.contentView.backgroundColor = [UIColor orangeColor];
            [self.contentView addSubview:label];
        }
    }

    return self;
}

- (void)prepareForReuse
{
    self.label.text = @"";
}

@end

我遇到的问题是,当我注册 class 时,它偶尔会显示单元格,并且没有在正确的位置显示它们。滚动时单元格也会随机 disappear/appear(通常不在同一位置)。

奇怪的是,如果我创建一个笔尖并注册笔尖而不是class,一切都很好。

我能想到的笔尖和 class 之间的唯一区别是笔尖,我使用 -(id)initWithCoder:(NSCoder *)aDecoder 而不是 -(instancetype)initWithFrame:(CGRect)frame

这里是集合视图文件供参考

.h

#import <UIKit/UIKit.h>

@interface TestCollectionView : UICollectionView

@end

.m

#import "TestCollectionView.h"
#import "TestCVCell.h"

@interface TestCollectionView () <UICollectionViewDataSource>

@property (nonatomic, strong) NSMutableArray *itemArray;

@end

@implementation TestCollectionView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame collectionViewLayout:[self collectionViewLayout]];

    if (self) {
        [self registerClass:[TestCVCell class] forCellWithReuseIdentifier:@"cell"];

        self.itemArray = [[NSMutableArray alloc] init];

        self.dataSource = self;

        for (int idx = 0; idx < 50; idx++) {
            [self.itemArray addObject:[NSNumber numberWithInt:idx]];
        }
    }

    return self;
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.itemArray.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    TestCVCell *cell = (TestCVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];

    cell.label.text = [NSString stringWithFormat:@"%@", [self.itemArray objectAtIndex:indexPath.item]];

    return cell;
}

- (UICollectionViewLayout *)collectionViewLayout
{
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.itemSize = CGSizeMake(50, 50);

    return layout;
}

@end

有没有人遇到过这个问题或类似的问题?

在此先感谢您的帮助。

这是你的问题,你的 TestCVCell Class 正在初始化期间初始化标签,然后 collectionView 正在重用相同的单元格,请记住在重用期间我们不初始化新对象,我们只是回收现有的一,因此您的标签永远不会在后续重复使用时设置。对您的 TestCVCell class.

进行以下更改

TestCVCell.h

@interface TestCVCell : UICollectionViewCell

@property (nonatomic) UILabel *label;

@end

您不再需要 iVar 标签。如果需要,我们将使用自动合成的 _label iVar。

使用延迟加载来初始化标签,它不仅聪明而且更干净,自定义 getter 如下所示,还记得在 prepareForReuse

#import "TestCVCell.h"

@implementation TestCVCell


- (UILabel *)label {

    if (!_label) {

        _label = [[UILabel alloc] initWithFrame:self.bounds];
        _label.textColor = [UIColor whiteColor];
        _label.textAlignment = NSTextAlignmentCenter;
        self.contentView.backgroundColor = [UIColor orangeColor];
        [self.contentView addSubview:_label];

    }

    return _label;
}

- (void)prepareForReuse
{
    [super prepareForReuse];
    self.label.text = @"";
}

@end

上面的代码只是在contentView没有初始化的情况下才给contentView添加label,只有在需要的时候才会初始化一个新的label,实现懒加载。删除整个 init 方法,不需要。以上是您对 TestCVCell 的整个实现。简洁易懂。