28

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

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

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

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

4

8 に答える 8

20

ついに!わかりました、これが私にとってこのクラッシュの原因でした。

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

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

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

于 2013-03-16T21:26:38.057 に答える
17

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

各補足ビューは、特定のインデックス パスに関連付けられています。そのインデックス パスにセルがない場合 (初期読み込み、行を削除したなど)、レイアウトのデリゲートを介して補助ビューの高さ 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 );

お役に立てれば!

于 2013-08-23T21:07:34.660 に答える
8

reloadDataperformBatchUpdates使用の全体的な目的は、変更をアニメーション化することであるため、私には機能しません。使用する場合reloadDataは、データを更新するだけで、アニメーションはありません。

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

申し訳ありませんが、いくつかの素晴らしいアニメーションの更新をしようとしているときにこのエラーが発生し続け、私のモデルは 100% 正しいので、ただイライラしています.ソリューションを完全に。

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

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

于 2013-01-02T15:41:59.653 に答える
3

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

いくつかのバリエーションを試しましたが、最終的にうまくいくと思われるのは です[self.collectionView reloadData]"self.collectionView"はコレクション ビューの名前です。

「UICollectionView クラス リファレンス」から直接、次のメソッドを試しました: 項目の挿入、移動、および削除。

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

  • deleteItemsAtIndexPaths:

  • insertItemsAtIndexPaths:

次にやってみmoveItemAtIndexPath:toIndexPath:ました。

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

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

そこで、「reloadData」メソッドを試してください。

于 2012-12-23T06:52:03.553 に答える
2

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

于 2014-04-25T15:41:01.910 に答える
2

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

その時点で、ヘッダー/フッターのサイズ/要素に nil を返そうとしましたが、これで問題が解決する場合があります。

オプション:

  1. 最後のアイテムの削除をアニメーション化する代わりに、テーブル ビュー全体を再読み込みします。
  2. サイズが 1 未満の非表示の基本セルを追加します。
于 2013-04-04T07:59:14.403 に答える
1

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

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

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

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

于 2013-05-01T02:23:39.033 に答える
0

グローバル インデックスがどのように増加したかはまだわかりませんでしたが、基になるデータソース配列に一時的なアイテムを挿入し、cellItemsを呼び出すこと[self.collectionview reloadData]で問題を解決しましたviewDidLoad()

これにより、コレクション ビューに一時的にプレースホルダー セルが挿入され、performBatchUpdates().

于 2012-12-27T03:00:59.387 に答える