UICollectionView PerformBatchUpdatesを使用して更新を実行します
-
11-12-2019 - |
質問
私は、私が動的に/動的にアイテムを挿入しようとしているUICollectionView
を持っています。だから私はイメージを非同期的にダウンロードするいくつかの関数を持っていて、アイテムをバッチで挿入したいです。
データを持っていたら、次のようにします。
[self.collectionView performBatchUpdates:^{
for (UIImage *image in images) {
[self.collectionView insertItemsAtIndexPaths:****]
}
} completion:nil];
.
***
の代わりに、NSIndexPaths
の配列を渡す必要があります。これは、挿入する新しいアイテムの場所を指すはずです。私は場所を提供した後、その位置に表示されるべき実際のイメージをどのように提供してから非常に混乱していますか?
ありがとう
更新:
resultsSize
は、self.results
のデータから新しいデータが追加される前のデータソース配列のサイズを含みます。
.[self.collectionView performBatchUpdates:^{
int resultsSize = [self.results count];
[self.results addObjectsFromArray:newImages];
NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];
for (int i = resultsSize; i < resultsSize + newImages.count; i++)
[arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
[self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];
} completion:nil];
解決
の挿入、削除、および移動部との項目からを" /introduction/introduction.html "rel=" NOREFERRER ">コレクション表示プログラミングガイドiOS ":
単一のセクションまたはアイテムを挿入、削除、または移動するには、次のようにしてください。 これらのステップ:
- データソースオブジェクトのデータを更新します。
- コレクションビューの適切なメソッドを呼び出して、セクションまたはアイテムを挿入または削除します。
通知する前にデータソースを更新することが重要です。 変更の収集ビューコレクションビューメソッドが想定されます データソースに現在正しいデータが含まれていること。そうであれば そうではない、コレクションビューはからの間違った項目のセットを受け取るかもしれません あなたのデータソースまたはそこにいないアイテムを尋ねてあなたをクラッシュさせる アプリ。
SOの場合は、最初にコレクションビューデータソースに画像を追加してから
insertItemsAtIndexPaths
を呼び出す必要があります。コレクションビューは、挿入されたアイテムのビューを提供するためにデータソースの委任関数に依頼します。
他のヒント
私はちょうどswiftで実装されました。その実装を共有したいのですが。 最初の初期化NSBlockOperationsの配列:
var blockOperations: [NSBlockOperation] = []
.
コントローラの変更、ine-init:
func controllerWillChangeContent(controller: NSFetchedResultsController) {
blockOperations.removeAll(keepCapacity: false)
}
.
DID変更オブジェクトメソッド:
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
if type == NSFetchedResultsChangeType.Insert {
println("Insert Object: \(newIndexPath)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.insertItemsAtIndexPaths([newIndexPath!])
}
})
)
}
else if type == NSFetchedResultsChangeType.Update {
println("Update Object: \(indexPath)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.reloadItemsAtIndexPaths([indexPath!])
}
})
)
}
else if type == NSFetchedResultsChangeType.Move {
println("Move Object: \(indexPath)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.moveItemAtIndexPath(indexPath!, toIndexPath: newIndexPath!)
}
})
)
}
else if type == NSFetchedResultsChangeType.Delete {
println("Delete Object: \(indexPath)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.deleteItemsAtIndexPaths([indexPath!])
}
})
)
}
}
.
DID変更区間法では:
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
if type == NSFetchedResultsChangeType.Insert {
println("Insert Section: \(sectionIndex)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.insertSections(NSIndexSet(index: sectionIndex))
}
})
)
}
else if type == NSFetchedResultsChangeType.Update {
println("Update Section: \(sectionIndex)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.reloadSections(NSIndexSet(index: sectionIndex))
}
})
)
}
else if type == NSFetchedResultsChangeType.Delete {
println("Delete Section: \(sectionIndex)")
blockOperations.append(
NSBlockOperation(block: { [weak self] in
if let this = self {
this.collectionView!.deleteSections(NSIndexSet(index: sectionIndex))
}
})
)
}
}
.
と最後に、DIDコントローラでコンテンツ方式を変更しました。
func controllerDidChangeContent(controller: NSFetchedResultsController) {
collectionView!.performBatchUpdates({ () -> Void in
for operation: NSBlockOperation in self.blockOperations {
operation.start()
}
}, completion: { (finished) -> Void in
self.blockOperations.removeAll(keepCapacity: false)
})
}
.
viewControllerが割り当て解除されようとしているときの操作をキャンセルするために、Deinitメソッドでもコードを追加しました。
deinit {
// Cancel all block operations when VC deallocates
for operation: NSBlockOperation in blockOperations {
operation.cancel()
}
blockOperations.removeAll(keepCapacity: false)
}
. 私は索引からのアイテムを削除しながら同様の問題に直面していましたが、これはperformBatchUpdates:
メソッドを使用している間にする必要があると思うものです。
1#最初にCollection Viewから項目を削除するには、DeleteItemAtIndexPathを呼び出します。
2#配列から要素を削除します。
3#データを再ロードすることでコレクションビューを更新します。
[self.collectionView performBatchUpdates:^{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
[self.addNewDocumentArray removeObjectAtIndex:sender.tag];
} completion:^(BOOL finished) {
[self.collectionView reloadData];
}];
.
これは私がすべてのクラッシュとアサーション失敗を削除するのを助けます。