UICollectionView relodItemsAtIndexPaths重新加载集合视图中的所有项目

时间:2020-04-15 19:59:03

标签: ios uicollectionview uikit

请考虑以下简单代码:

@interface ViewController ()<UICollectionViewDelegate, UICollectionViewDataSource>

@property (nonatomic, strong) IBOutlet UICollectionView* collectionView;

@end

@implementation ViewController

- (void)viewDidLoad {
     [super viewDidLoad];

     self.view.backgroundColor = [UIColor redColor];

     [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"Hello"];

     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

         [self.collectionView reloadItemsAtIndexPaths:@[ [NSIndexPath indexPathForItem:0 inSection:0]]];
});
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 20;
}

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"RELOADING %ld", indexPath.row);

    NSString* identifier = @"Hello";

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

    NSArray* colors = @[[UIColor redColor], [UIColor blueColor]];

    cell.backgroundColor = colors[indexPath.row % colors.count];

    return cell;
}

@end

因此,这里有一个非常基本的UICollectionView是在情节提要中创建的。没什么特别的。因此,我正在尝试仅重新加载一项。当我调用reloadItemsAtIndexPaths时,它将首先重新加载所有项目,然后立即重新加载我实际要重新加载的项目。这显然是错误的。我需要避免做所有这些额外的工作。为什么它甚至表现得如此?是iOS的错误吗?能做些什么才能使其正常工作?

1 个答案:

答案 0 :(得分:2)

如果您的UICollectionView使用的布局可能可能具有动态尺寸的单元格,则每次更新单元格时都会重新评估该布局。这意味着将为许多单元格调用cellForItemAtIndexPath。

不过请注意,使用您的代码 只有项目0,0 实际上得到更新。

将您的代码更改为此(请注意,我将您的调度时间更改为3秒,因此我们不必等那么久就能看到更新):

@interface WithCollectionViewController ()<UICollectionViewDelegate, UICollectionViewDataSource>

@property (nonatomic, strong) IBOutlet UICollectionView* collectionView;
@property (nonatomic, strong) NSArray *colors;

@end

@implementation WithCollectionViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // start with colors array of red and blue
    self.colors = @[[UIColor redColor], [UIColor blueColor]];

    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"Hello"];
    [self.collectionView setDataSource:self];
    [self.collectionView setDelegate:self];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"calling RELOAD");
        // change colors array to green and yellow
        self.colors = @[[UIColor greenColor], [UIColor yellowColor]];
        [self.collectionView reloadItemsAtIndexPaths:@[ [NSIndexPath indexPathForItem:0 inSection:0]]];
    });

}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 20;
}

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

    NSLog(@"RELOADING %ld", indexPath.row);

    NSString* identifier = @"Hello";

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

    cell.backgroundColor = self.colors[indexPath.row % self.colors.count];

    return cell;

}

@end

您将首先获得红色/蓝色图案。触发reloadItemsAtIndexPaths后,颜色数组将变为绿色/黄色...您将看到所有20个单元的调试输出,但 只有第一个单元 将更改颜色(变为绿色)。

enter image description here

如果您不想重复通话,请为您的版式设置固定的项目大小:

@interface WithCollectionViewController ()<UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>

@property (nonatomic, strong) IBOutlet UICollectionView* collectionView;
@property (nonatomic, strong) NSArray *colors;

@end

@implementation WithCollectionViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // start with colors array of red and blue
    self.colors = @[[UIColor redColor], [UIColor blueColor]];

    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"Hello"];
    [self.collectionView setDataSource:self];
    [self.collectionView setDelegate:self];

    UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
    layout.itemSize = CGSizeMake(50, 50);
    [self.collectionView setCollectionViewLayout:layout];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"calling RELOAD");
        // change colors array to green and yellow
        self.colors = @[[UIColor greenColor], [UIColor yellowColor]];
        [self.collectionView reloadItemsAtIndexPaths:@[ [NSIndexPath indexPathForItem:0 inSection:0]]];
    });

}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 20;
}

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

    NSLog(@"RELOADING %ld", indexPath.row);

    NSString* identifier = @"Hello";

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

    cell.backgroundColor = self.colors[indexPath.row % self.colors.count];

    return cell;

}

@end

结果相同,但是只为您指定的0,0索引路径调用cellForItemAtIndexPath