UICollectionView断言失败

jaj*_*o87 59 objective-c ios6 uicollectionview

我在执行insertItemsAtIndexPaths中遇到此错误UICollectionView

断言失败:

-[UICollectionViewData indexPathForItemAtGlobalIndex:], 
/SourceCache/UIKit/UIKit-2372/UICollectionViewData.m:442
2012-09-26 18:12:34.432  
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'request for index path for global index 805306367 
when there are only 1 items in the collection view'
Run Code Online (Sandbox Code Playgroud)

我检查过,我的数据源只包含一个元素.有关为何会发生这种情况的任何见解?如果需要更多信息,我绝对可以提供.

Jay*_*sky 68

将第一个单元格插入集合视图时遇到了同样的问题.我通过更改代码来修复问题,以便调用UICollectionView

- (void)reloadData
Run Code Online (Sandbox Code Playgroud)

插入第一个单元格时的方法,但是

- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths
Run Code Online (Sandbox Code Playgroud)

插入所有其他单元格时.

有趣的是,我也有一个问题

- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths
Run Code Online (Sandbox Code Playgroud)

删除最后一个单元格时 我做了和以前一样的事情:reloadData在删除最后一个单元格时调用.

  • 这似乎是正确的答案.如果要插入第一个单元格,则会发生崩溃.关于这个问题有一个开放的雷达:http://openradar.appspot.com/12954582,它说只有在你使用'装饰视图'(章节页眉或页脚)时才会出现问题. (14认同)
  • 补充视图并在第一项上使用reloadData和在以下项上使用insertItemsAtIndexPaths,对我来说不起作用.但是,如果我禁用补充视图,那么它可以工作 如果我只使用reloadData它可以工作.遗憾的是,我想将-insertItemsAtIndexPaths与我的KVO代码一起使用. (2认同)
  • 在iOS7中,除非我使用reloadData进行单元格插入和删除,否则它总是会崩溃!我有一个复杂的headerView,并使用简单的单元格进行测试 - 效果很好.当细胞变得更复杂时,崩溃就开始了...... (2认同)

neo*_*eye 11

在插入单元格之前插入部分#0似乎使UICollectionView很高兴.

NSArray *indexPaths = /* indexPaths of the cells to be inserted */
NSUInteger countBeforeInsert = _cells.count;
dispatch_block_t updates = ^{
    if (countBeforeInsert < 1) {
        [self.collectionView insertSections:[NSIndexSet indexSetWithIndex:0]];
    }
    [self.collectionView insertItemsAtIndexPaths:indexPaths];
};
[self.collectionView performBatchUpdates:updates completion:nil];
Run Code Online (Sandbox Code Playgroud)

  • 为了使这个工作,我不得不调整`numberOfSectionsInCollectionView:`方法的返回值.如果您的集合为空,则返回0个部分,如果集合不是,则返回1.如果您没有实现此方法或返回0,则会出现"无效更新"错误,这些错误会导致插入后不正确的部分数量. (2认同)

iwa*_*bed 5

我在这里发布了一个解决这个问题的方法:https://gist.github.com/iwasrobbed/5528897

.m文件顶部的私人类别中:

@interface MyViewController ()
{
    BOOL shouldReloadCollectionView;
    NSBlockOperation *blockOperation;
}
@end
Run Code Online (Sandbox Code Playgroud)

那么你的委托回调将是:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    shouldReloadCollectionView = NO;
    blockOperation = [NSBlockOperation new];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    __weak UICollectionView *collectionView = self.collectionView;
    switch (type) {
        case NSFetchedResultsChangeInsert: {
            [blockOperation addExecutionBlock:^{
                [collectionView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
            }];
            break;
        }

        case NSFetchedResultsChangeDelete: {
            [blockOperation addExecutionBlock:^{
                [collectionView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
            }];
            break;
        }

        case NSFetchedResultsChangeUpdate: {
            [blockOperation addExecutionBlock:^{
                [collectionView reloadSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
            }];
            break;
        }

        default:
            break;
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    __weak UICollectionView *collectionView = self.collectionView;
    switch (type) {
        case NSFetchedResultsChangeInsert: {
            if ([self.collectionView numberOfSections] > 0) {
                if ([self.collectionView numberOfItemsInSection:indexPath.section] == 0) {
                    shouldReloadCollectionView = YES;
                } else {
                    [blockOperation addExecutionBlock:^{
                        [collectionView insertItemsAtIndexPaths:@[newIndexPath]];
                    }];
                }
            } else {
                shouldReloadCollectionView = YES;
            }
            break;
        }

        case NSFetchedResultsChangeDelete: {
            if ([self.collectionView numberOfItemsInSection:indexPath.section] == 1) {
                shouldReloadCollectionView = YES;
            } else {
                [blockOperation addExecutionBlock:^{
                    [collectionView deleteItemsAtIndexPaths:@[indexPath]];
                }];
            }
            break;
        }

        case NSFetchedResultsChangeUpdate: {
            [blockOperation addExecutionBlock:^{
                [collectionView reloadItemsAtIndexPaths:@[indexPath]];
            }];
            break;
        }

        case NSFetchedResultsChangeMove: {
            [blockOperation addExecutionBlock:^{
                [collectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
            }];
            break;
        }

        default:
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    // Checks if we should reload the collection view to fix a bug @ http://openradar.appspot.com/12954582
    if (shouldReloadCollectionView) {
        [self.collectionView reloadData];
    } else {
        [self.collectionView performBatchUpdates:^{
            [blockOperation start];
        } completion:nil];
    }
}
Run Code Online (Sandbox Code Playgroud)

对于这种方法的信用归功于Blake Watters.