9

UICollectionViewFlowLayout を垂直方向に使用している典型的な UICollectionView があります。コレクションビューにデータを入力するために、ページネーションを備えた残りの API を使用しています。ダウンロードする次のページをトリガーするために、フッター レイアウトを要求するときにデリゲートを使用しています。

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
    RDLoadMoreReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"RDLoadMoreReusableView" forIndexPath:indexPath];
    view.delegate = self;
    [view start];
    [self loadNextPageOfAssets];
    return view;
}

私のloadNextPageOfAssetsの背後にあるコードは次のとおりです。

-(void)loadNextPageOfAssets{
    __weak RDRadiusGridViewController *weakSelf = self;

    // Increment page and request assets. They are added to cluster.assets before the completion block is called.
    self.cluster.pagination.page++;
    [self.cluster requestAssetsWithCompletionBlock:^(NSArray *assets) {

        SM_LOG_DEBUG(@"page.total: %ld assets.count: %ld", self.cluster.pagination.totalCount, (long)assets.count);

        NSMutableArray *indexPaths = [[NSMutableArray alloc]initWithCapacity:assets.count];
        for(NSUInteger index = 0; index < assets.count; index++){
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.cluster.assets.count - assets.count + index inSection:0];
            SM_LOG_DEBUG(@"Inserting indexPath: %ld:%ld", (long)indexPath.item, (long)indexPath.section);
            [indexPaths addObject:indexPath];
        }
        [weakSelf.collectionView performBatchUpdates:^{
            [weakSelf.collectionView insertItemsAtIndexPaths:indexPaths];
        } completion:^(BOOL finished) {

        }];

//            [weakSelf.collectionView reloadData];
    }];
}

実行すると、ViewController に移動して、読み込まれたアセットの最初のページを確認できます。下にスクロールすると、フッター ビュー (スピナーを含む) が表示されますが、次の行の例外ブレーク ポイントでコードが中断されます。

[weakSelf.collectionView insertItemsAtIndexPaths:indexPaths];

-[UICollectionViewData layoutAttributesForSupplementaryElementOfKind:atIndexPath:]、/SourceCache/UIKit/UIKit-3185.20/UICollectionViewData.m:829 でのアサーションの失敗


次に続行すると、次のエラーでクラッシュします。

2014-06-11 16:39:58.335 Radius-iOS[4901:525006] * キャッチされていない例外 'NSInternalInconsistencyException' が原因でアプリを終了しています。 - 0}' *最初のスロー コール スタック:


これは私には不可解です。layoutAttributesForSupplementaryElementOfKind は、レイアウト クラスと関係があるように思えますが、提供されている既定のフロー レイアウトではなく、カスタム フロー レイアウトを使用していません。Apple のコードは狂っているように聞こえますが、私はすべてを正しく使用していると感じています。

通話を移動すると、次のようになります。

[self loadNextPageOfAssets];

補足セルのデキューから UICollectionViewCell デキューに移動し、フッター ビューをすべて一緒に削除すると、挿入がうまく機能します。

今のところ、挿入の代わりに reloadData を呼び出していますが、これは醜いです。

フッターについて何か見落としていますか?

4

4 に答える 4

10

VaporwareWolf が提供する答えはちょっとしたハックです。ゼロ サイズではなく小さなサイズを返すことで、補助ビューは常に存在しますが、サイズが小さすぎて見えません。それがNSInternalInconsistencyExceptionを修正する理由です

しかし、本当の解決策があります。

データをデータソースに追加した 、を呼び出すinsertItemsAtIndexPathsに、collectionview のレイアウトを無効にして変更を認識させます。

Objective-C

[self.collectionView.collectionViewLayout invalidateLayout]

迅速

collectionView.collectionViewLayout.invalidateLayout()
于 2016-04-05T21:21:55.920 に答える
0

UICollectionView のバグに関するロシア語の巨大な記事があります: http://habrahabr.ru/post/211144/

あなたの問題を解決するかもしれないその記事からのいくつかの方法はここにあります:

@try {
    [self.collectionView insertItemsAtIndexPaths:indexPaths];
}
@catch (NSException *exception) {}

また

[self.collectionView performBatchUpdates:^{
        [self.collectionView reloadData];
    } completion:nil];
于 2014-06-19T18:39:57.627 に答える