重用单元格 UICollectionView - 某些单元格没有被选中

Posted

技术标签:

【中文标题】重用单元格 UICollectionView - 某些单元格没有被选中【英文标题】:Reusing cells UICollectionView - some cells don't get selected 【发布时间】:2013-04-06 13:23:26 【问题描述】:

UICollectionView 中,我有一个自定义UICollectionViewCellClass,其中 prepareForReuse 被默认格式化人员覆盖。

我从 didSelectItemAtIndexPath: 获得了一个包含 NSIndexPathsNSMutableArray

cellForItemAtIndexPath: 我重新格式化选定的单元格,使它们看起来被选中。

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

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

NSString *title = self.ingredientsBook.names[indexPath.item];

cell.label.text = title;

if ([self isSelectedIndexPath:indexPath])

    cell.backgroundColor = [UIColor whiteColor];
    cell.label.textColor = [UIColor blueColor];

return cell;



-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

self.searchButton.enabled = YES;

ButtonCell *cell = (ButtonCell *)[collectionView cellForItemAtIndexPath:indexPath];
[selectedCellIndexPaths addObject:indexPath];
NSLog(@"%@", selectedCellIndexPaths);
cell.backgroundColor = [UIColor whiteColor];
cell.label.textColor = [UIColor blueColor];

NSString *name = self.ingredientsBook.names[indexPath.item];
[self.selectedIngredientNames addObject:name];



问题是当我点击第一个单元格时,无法选择第 16 个或第 17 个单元格。 或者,如果我点击前三个,则无法选择最后三个。 我想didSelectItemAtIndexPath 没有被调用。

我觉得它必须非常简单,但我现在看不到。

我尝试将NSLogs放入shouldSelectItemAtIndexPath 以了解是否调用了该方法并且根本没有调用该方法。当所选单元格和有问题的单元格之间的距离为 16 个单元格时,就会发生这种情况。

这里是其他数据源方法和isSelectedIndexPath:

-(BOOL)isSelectedIndexPath:(NSIndexPath *)indexPath

for (NSIndexPath *test in selectedCellIndexPaths)
    if (test == indexPath)
        return YES;
    


return NO;


-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

return [self.ingredientsBook.names count];


-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

return 1;


-(BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath

NSLog(@"%@", indexPath);

return YES;



-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath

self.searchButton.enabled = ([[collectionView indexPathsForSelectedItems] count] > 0);

ButtonCell *cell = (ButtonCell *)[collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor blackColor];
cell.label.textColor = [UIColor whiteColor];

[selectedCellIndexPaths removeObject:indexPath];
NSString *name = self.ingredientsBook.names[indexPath.item];
[self.selectedIngredientNames removeObject:name];




【问题讨论】:

什么是isSelectedIndexPath?你在哪里创造它?我认为您还需要一个“其他”部分来说明如果 [self isSelectedIndexPath:indexPath] 返回 false 时单元格应该是什么样子。 它是一种检查 indexPath 是否包含在 NSIndexPaths 的 NSMutableArray 中的方法。当 indexPath 等于数组中选定的一个时,它总是返回 false。 好的,您是否将“else”部分添加到 if 语句中以查看是否有帮助。由于单元格重用,如果 if 语句为 false,则需要将单元格的外观设置为未选中状态。 如果不查看更多代码,我无法解释每 16 个单元格的内容。我在您发布的内容中看不到任何可以解释这一点的内容。您应该发布所有数据源方法和 isSelectedIndexPath: 方法。 我尝试添加“其他部分”,但似乎不受此影响。当我记录 shouldSelectItemAtIndexPath: 我没有得到答案。好像该方法尚未被调用。但我正在点击那个单元格!太疯狂了 【参考方案1】:

我发现了两个问题。 prepareForReuse 方法似乎搞砸了,所以我把它删除了。不过,主要问题是您实现 isSelectedIndexPath: 的方式。一旦在您遍历项目时找到第一个选定项目,它就会返回 YES 并退出循环。您要做的就是检查 indexPath 是否包含在 selectedCellIndexPaths 数组中:

-(BOOL)isSelectedIndexPath:(NSIndexPath *)indexPath

    if ([selectedCellIndexPaths containsObject:indexPath]) 
        return YES;
    else
        return NO;
    

或者,如果您更喜欢使用更简洁的语法,可以将 if-else 块替换为:

return  ([selectedCellIndexPaths containsObject:indexPath])? YES : NO;

【讨论】:

即使进行了这些更改,问题仍然存在。不过非常感谢您的耐心和坚持。 对不起,我想删除 prepareForReuse。现在一切都很好。再次感谢您的耐心和坚持。 只是:return [selectedCellIndexPaths containsObject:indexPath];【参考方案2】:

我最近在我的应用程序中遇到了完全相同的问题。 UICollectionViewCell 选择在 ios 8.3 之前正常工作,随后我开始看到一些奇怪的行为。实际未选择的单元格将显示为已选中,而其他单元格似乎随机无法选择。

我在 UICollectionViewCell 子类上实现了自定义 setSelectedprepareForResuse 方法:

 -(void)setSelected:(BOOL)selected

     [super setSelected:selected];

    if (selected)
    
        [[self selectedIndicator] setHidden:NO];
    
    else
    
        [[self selectedIndicator] setHidden:YES];
    


-(void)prepareForReuse

    [[self imageView] setImage:nil];

prepareForReuse 方法只是在自定义单元格中重置图像视图。

在我的prepareForReuse 方法中,我没有调用[super prepareForReuse](根据文档,默认情况下它什么都不做)。当我添加对[super prepareForReuse] 的调用时,所有选择都按预期工作。尽管 Apple 声明默认实现什么都不做,但他们也建议应该调用 super。遵循此建议解决了我的问题。

【讨论】:

【参考方案3】:

在 iOS 10 中,我发现在启用预取时以编程方式清除启用了多选的 UICollectionView 是错误的。当然,预取在 iOS 10 中是默认开启的。

【讨论】:

以上是关于重用单元格 UICollectionView - 某些单元格没有被选中的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 不重用单元格

UICollectionView 重用单元格问题

拖放 UICollectionView 单元格重用问题

在 UICollectionView 上禁用单元格重用

UICollectionView 重用单元格背景问题

如何不在 UICollectionView 中重用单元格 - Swift