【问题标题】:Updating cells in UICollectionView that scrolls - app crashes when deleting off-screen cells更新 UICollectionView 中滚动的单元格 - 删除屏幕外单元格时应用程序崩溃
【发布时间】:2013-06-17 01:17:30
【问题描述】:

我的应用程序包含一个 UICollectionView,它显示了许多用于纸牌匹配游戏的自定义子视图。基本上,当三张卡片匹配时,包含它们的单元格将从集合视图中删除。当所有三个单元格都在可滚动屏幕上可见时,我的删除功能起作用,但当一两个单元格不在屏幕上时则不起作用。发生的情况是屏幕上的单元格将被删除,但是当我尝试向上滚动以查看其他单元格(也应该被删除)时,应用程序崩溃了。

下面是我的卡片更新功能的代码:

- (void) updateCell: (SetCardCell*) cell withCard: (SetsCard *) cardInModel {
    if ([cell isKindOfClass: [SetCardCell class]]){
        if ([cell.setCardView isKindOfClass:[SetCardView class]]) {

            // various actions to match view with model

            SetCardView *cardView = cell.setCardView;
            [cardView setNeedsDisplay];

            // do things to UI if card is faced up or unplayable

            if (!cardInModel.isUnplayable) {
                if (cardInModel.isFaceUp) {
                    cell.setCardView.alpha = 0.3;
                } else {
                    cell.setCardView.alpha = 1;
                }
            } else {
                // remove the cell - this is where the problem is

                NSLog(@"%@", cell.description);  ** returns a cell ** 
                NSLog(@"%@", [self.collectionView indexPathForCell:cell].description); ** returns (null) when the cell is offscreen, but a normal index path if otherwise **

                [self.game.cards removeObjectsInArray:@[cardInModel]];
                [self.collectionView deleteItemsAtIndexPaths:@[[self.collectionView indexPathForCell:cell]]];
            }
        }
    }
}

关于如何解决这个问题的任何想法?非常感谢!

编辑:我忘记了以下错误消息:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'

【问题讨论】:

    标签: ios xcode scroll uicollectionview


    【解决方案1】:

    如您所见,当使用 indexPathForCell 时,您会得到一个当前不可见的单元格的 nil 索引路径。当您尝试从中创建一个数组以传递给 delete 方法时,这会导致崩溃。 delete 方法本身并没有崩溃,只是创建了一个数组。

    您不应该使用单元来推动更新。您需要尽快获得对 model 中对象的引用,并派生索引路径并从中执行删除。单元格只是模型表示的一部分。

    查看您的代码,一种可能的解决方法是从cardInModel 在其数组中的位置导出索引路径(在您删除它之前?)

    【讨论】:

    • 谢谢,我将代码更改为:NSIndexPath *indexPathToBeRemoved = [NSIndexPath indexPathForRow:[self.game.cards indexOfObject:cardInModel] inSection:0]; [self.game.cards removeObjectsInArray:@[cardInModel]]; [self.collectionView deleteItemsAtIndexPaths:@[indexPathToBeRemoved]]; 我不再收到异常,但单元格并未完全删除。随着剩余视图的移动,应该删除的视图留在新单元格的背景中,因此两个视图之间存在重叠。与新视图不同,这些旧视图根本不受更改的影响
    • 在重用它们之前,您必须从单元格中删除旧的子视图。最简单的方法如下: [cell.contentView.subviews makeObjectsPerformSelector: @selector(removeFromSuperview)];
    • @RegularExpression 可能是对的。您的新问题听起来像是单元重用问题。
    • @RegularExpression 我尝试在从集合视图中删除项目之前放置您建议的代码。它摆脱了重叠问题,但是当我删除单元格时,一些随机单元格现在就消失了。它们仍然是可点击的,它们仍然有内容,只是不可见。当我向上和向下滚动时,这些单元格(只是集合视图中的单元格,甚至不是已删除单元格所在的单元格)只会随机出现/消失。你有什么想法吗?
    • @RegularExpression 实际上,我已经更仔细地检查过,重叠问题仍然存在,即使使用您的代码也是如此。是否有可能通过在删除单元格之前删除子视图,下次重用单元格时将不再有子视图?
    【解决方案2】:

    如果你这样做:

    [self.collectionView deleteItemsAtIndexPaths:@[[self.collectionView indexPathForCell:cell]]];
    

    并且 indexPath 返回 nil(如果当前未显示单元格,则可能会返回),您将收到异常,因为 deleteItemsAtIndexPaths 不能传递 nil。

    【讨论】:

    • 是的,我忘了提到例外!这是:*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'
    • 这不是我期望你得到的例外。确切地说,您在哪条线上遇到了异常?如果它是第二个 NSLog,你知道你得到的是单元格或描述的 nil。真的会用调试器检查这些语句中的每个变量,因为问题必须在其中一个中。
    • 我在这条线上遇到了异常:[self.collectionView deleteItemsAtIndexPaths:@[[self.collectionView indexPathForCell:cell]]]; 我会尝试调试器并告诉你它是如何工作的
    猜你喜欢
    • 2016-09-25
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多