UICollectionView 在刷新时重复和重新排序单元格内容

Posted

技术标签:

【中文标题】UICollectionView 在刷新时重复和重新排序单元格内容【英文标题】:UICollectionView Repeats and Reorders Cell Content When Refreshed 【发布时间】:2014-05-16 22:40:34 【问题描述】:

我正在尝试完成 iTunes U CS193P ios 编程课程。我在使用 UICollectionView 来显示卡片作为 Set 游戏实现的一部分时遇到了一些问题。单击导致UICollectionView 刷新的卡片时,我看到了一个非常奇怪的行为。内容将被重新排序,有时会在视图中重复。请参阅here 之前和之后的两个示例。

我相当肯定这与我的UICollectionView 实现有关,因为游戏逻辑已经使用按钮进行了测试。

点击“视图控制器”中的代码:

- (IBAction)touchCard:(UITapGestureRecognizer *)sender 
    CGPoint tapLocation = [sender locationInView:self.cardCollectionView];
    NSIndexPath *indexPath = [self.cardCollectionView indexPathForItemAtPoint:tapLocation];
    if (indexPath) 
        [self.game chooseCardatIndex:indexPath.item];
        [self updateUI];
    

updateUI 代码:

- (void)updateUI

    // Reload data for cardCollectionView
    [self.cardCollectionView reloadData];

    // For each cell within the UICollectionViewCell
    for (UICollectionViewCell *cell in [self.cardCollectionView visibleCells]) 

        NSIndexPath *indexPath = [self.cardCollectionView indexPathForCell:cell];
        Card *card = [self.game cardAtIndex:indexPath.item];
        if([card isKindOfClass:[SetCard class]]) 
            SetCard *setcard = (SetCard *)card;
            NSLog([NSString stringWithFormat:@"index %d updated with %d,%d,%d,%d",indexPath.item,setcard.rank,setcard.color,setcard.shape,setcard.pattern]);
            // Updates individual cards for each cardCollectionView
            [self updateCell:cell usingCard:card animated:YES];
        
    

这会更新单元格视图:

- (void)updateCell:(UICollectionViewCell *)cell usingCard:(Card *)card animated:(BOOL)animated

    setCardView *cardView = ((setCardCellView *)cell).setCardV;

    if([card isKindOfClass:[SetCard class]]) 
        SetCard *setCard = (SetCard *)card;

        // Set attributes of the card in the cardView
        cardView.rank = setCard.rank;
        cardView.shape = setCard.shape;
        cardView.pattern = setCard.pattern;
        cardView.color = setCard.color;

        // Set chosen cards
        cardView.selected = setCard.isChosen;
    

终于collectionView所需的方法cellForItemAtIndexPath

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[self reuseIdentifier] forIndexPath:indexPath];
    Card *card = [self.game cardAtIndex:indexPath.item];

    [self updateCell:cell usingCard:card animated:YES];
    return cell;

感谢您的帮助。

【问题讨论】:

【参考方案1】:

当您实现 cellForRowAtIndexPath / cellForItemAtIndexPath 方法时,您必须完全配置从 dequeue 方法返回的每个单元格。

只有当该行的卡片对象是 SetCard 类型时,您的代码才会配置单元格。如果卡片对象不是 SetCard,则不理会该单元格。这意味着,如果您从 dequeue 方法获得的单元格以前用于显示 SetCard,但卡片对象不是 SetCard,则单元格的视图不会更改,并且仍会显示旧值。

如果卡片对象不属于 SetCard 类,则在 if 语句中添加一个 else 子句,将字段设置回默认状态。

【讨论】:

我添加了一个 else 子句,如果不是 SetCard 类则输出到日志。不幸的是,在测试中,else 子句永远不会执行,仍然会看到重新排序和复制单元格的相同行为。

以上是关于UICollectionView 在刷新时重复和重新排序单元格内容的主要内容,如果未能解决你的问题,请参考以下文章

iOS UICollectionView 推送刷新时的意外行为

应用 NSDiffableDataSourceSnapshot 时,ViewController 中的 UICollectionView 拉取刷新跳转

禁用 UICollectionView 顶部的“拉动刷新”空间

Swift:如何在设备旋转后刷新UICollectionView布局

UICollectionView 刷新数据

刷新、更新和重绘有啥区别?