请考虑以下简单代码:
@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的错误吗?能做些什么才能使其正常工作?
答案 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个单元的调试输出,但 只有第一个单元 将更改颜色(变为绿色)。
如果您不想重复通话,请为您的版式设置固定的项目大小:
@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
。