web-dev-qa-db-ja.com

UICollectionViewData indexPathForItemAtGlobalIndexでのアサーションエラー

performBatchUpdates()を使用してコレクションビューを更新しています。ここでは、完全な更新を行っています。つまり、そこにあったものをすべて削除し、すべてを再挿入しています。バッチ更新は、NSMutableArraybingDataItems)に接続されているObserverの一部として行われます。

cellItemsは、コレクションビューに挿入されている、またはこれから挿入されるアイテムを含む配列です。

これがコードです:

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    cultARunner *_cultARunner = [cultARunner getInstance];
    if ( [[_cultARunner bingDataItems] count] ) {
        [self.collectionView reloadData];
        [[self collectionView] performBatchUpdates: ^{

            int itemSize = [cellItems count];
            NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];

            // first delete the old stuff
            if (itemSize == 0) {
                [arrayWithIndexPaths addObject: [NSIndexPath indexPathForRow: 0 inSection: 0]];
            }
            else {
                for( int i = 0; i < cellItems.count; i++ ) {
                    [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
                }
            }
            [cellItems removeAllObjects];
            if(itemSize) {
                [self.collectionView deleteItemsAtIndexPaths:arrayWithIndexPaths];
            }

            // insert the new stuff
            arrayWithIndexPaths = [NSMutableArray array];
            cellItems = [_cultARunner bingDataItems];
            if ([cellItems count] == 0) {
                [arrayWithIndexPaths addObject: [NSIndexPath indexPathForRow: 0 inSection: 0]];
            }
            else {              
                for( int i = 0; i < [cellItems count]; i++ ) {
                    [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
                }
            }
            [self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];
        }
        completion:nil];
    }
}

私はこのエラーを受け取りますが、いつもではありません(なぜですか?)

2012-12-16 13:17:59.789 [16807:19703] *** Assertion failure in -[UICollectionViewData indexPathForItemAtGlobalIndex:], /SourceCache/UIKit_Sim/UIKit-2372/UICollectionViewData.m:442
2012-12-16 13:17:59.790 [16807:19703] DEBUG:    request for index path for global index 1342177227 when there are only 53 items in the collection view

ここで同じ問題に言及している唯一のスレッドをチェックしました: ICollectionView Assertion failure ですが、明確ではありません。つまり、performBatchUpdates()ブロックで[collectionview reloadData]を実行することはお勧めできません。

ここで何がうまくいかないのかについての提案はありますか?

27
DancingJohn

最後に! OK、このクラッシュの原因は次のとおりです。

前述のように、コレクションビューにカスタムスタイルのセクションヘッダーを提供するために、補足ビューを作成していました。

問題はこれです。補足ビューのindexPathは、コレクション内の現存するセルのindexPathに対応している必要があります。補足ビューのインデックスパスに対応する通常のセルがない場合、アプリケーションはクラッシュします。コレクションビューは、更新手順中になんらかの理由で補足ビューのセルの情報を取得しようとすると思います。見つからない場合はクラッシュします。

うまくいけば、これもあなたの問題を解決するでしょう!

20
Ash

これは、このクラッシュに対する適切な回避策です。

補足ビューのそれぞれは、特定のインデックスパスに関連付けられています。そのインデックスパスにセルがない場合(初期ロード、行の削除など)、レイアウトのデリゲートを介して補助ビューの高さ0を返します。

したがって、フローレイアウトの場合、UICollectionViewDelegateFlowLayoutの実装

(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section

メソッド(およびフッターを使用している場合は対応するフッターメソッド)と次のロジック

if ( you-have-a-cell-at-the-row-for-this-section )
    return myNormalHeaderSize;
else return CGSizeMake( 0,0 );

お役に立てれば!

17
deepseadiving

reloadDataを使用する目的はすべて、変更をアニメーション化することなので、performBatchUpdatesは機能しません。 reloadDataを使用する場合、データは更新されますが、アニメーションは更新されません。

したがって、「performBatchUpdatesreloadDataで置き換える」という提案は、「やろうとしていることをあきらめる」と言っています。

申し訳ありませんが、すばらしいアニメーションの更新を試みている間にこのエラーが何度も表示され、モデルが100%正しいので、イライラしています。完全にソリューション。

私の意見では、コレクションビューはまだバグがあり、複雑なアニメーションの更新を行うことはできても、それを行うことはできません。これは以前はテーブルビューでも同じでしたが、現在はかなり安定しています(ただし時間がかかりました)。

//編集(2013年9月1日)報告されたバグは現在クローズされているため、この問題はAppleによってすでに解決されているようです。

8
czechboy

私も同じ問題を抱えています。

私はいくつかのバリエーションを試しましたが、動作するように見える最後のものは[self.collectionView reloadData]、 どこ "self.collectionView"は、コレクションビューの名前です。

「UICollectionViewクラスリファレンス」から直接、アイテムの挿入、移動、削除のメソッドを試しました。

これらは最初、アイテムをあるセクションから別のセクションに「移動」するために使用されました。

  • deleteItemsAtIndexPaths:

  • insertItemsAtIndexPaths:

次に、moveItemAtIndexPath:toIndexPath:

それらはすべて次のエラーを生成しました:

-[UICollectionViewData indexPathForItemAtGlobalIndex:]、/ SourceCache/UIKit_Sim/UIKit-2372/UICollectionViewData.m:442でのアサーションエラー

したがって、「reloadData」メソッドを試してください。

3
Jim

ヘッダー/フッターを含むセクションから最後のセルを削除すると、バグが表示されます。

その時に私はヘッダー/フッターのサイズ/要素のnilを返そうとしました、そしてこれは時々問題を修正します。

オプション:

  1. 最後のアイテムの削除をアニメーション化する代わりに、テーブルビュー全体を再ロードします。
  2. サイズが1未満の追加の非表示の基本セルを追加します。
2
HeikoG

このエラーにつながる可能性のあるチーズボールの間違いは、同じビューコントローラの複数のcollectionViewで同じUICollectionViewFlowLayoutを再利用することです!コレクションビューごとに異なるflowLayoutsを初期化するだけで、準備完了です。

2
ColossalChris

コレクションビューからセルの1つを削除すると、この問題が発生しました。

問題は、カスタムレイアウトを使用していて、layoutAttributesForElementsInRectを呼び出すと、削除後にコレクションビューのセル数より多くのセルが返されていたことです。

どうやらUICollectionViewは、セルの数をチェックせずに、メソッドによって返された配列を反復処理するだけです。

同じ数のレイアウト属性を返すようにメソッドを変更すると、クラッシュが解決しました。

1
Allen Zeng