objective-c - uicollectionviewcontroller - uicollectionviewcell indexpath
UICollectionView Realizando Actualizaciones usando performBatchUpdates (3)
Acabo de implementar eso con Swift. Entonces me gustaría compartir mi implementación. Primero inicialice una matriz de NSBlockOperations:
var blockOperations: [NSBlockOperation] = []
En el controlador cambiará, reinicia la matriz:
func controllerWillChangeContent(controller: NSFetchedResultsController) {
blockOperations.removeAll(keepCapacity: false)
}
En el método did object de cambio:
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!])
}
})
)
}
}
En el método de la sección did change:
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))
}
})
)
}
}
Y finalmente, en el controlador did cambió el método de contenido:
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)
})
}
Personalmente, también agregué un código en el método de deinit, para cancelar las operaciones cuando el ViewController está a punto de ser desasignado:
deinit {
// Cancel all block operations when VC deallocates
for operation: NSBlockOperation in blockOperations {
operation.cancel()
}
blockOperations.removeAll(keepCapacity: false)
}
Tengo un UICollectionView
que estoy tratando de insertar elementos dinámicamente / con animación. Así que tengo alguna función que descarga imágenes de forma asíncrona y me gustaría insertar los artículos en lotes.
Una vez que tenga mis datos, me gustaría hacer lo siguiente:
[self.collectionView performBatchUpdates:^{
for (UIImage *image in images) {
[self.collectionView insertItemsAtIndexPaths:****]
}
} completion:nil];
Ahora, en lugar del ***
, debería pasar un conjunto de NSIndexPaths
, que debe señalar la ubicación de los nuevos elementos que se insertarán. Estoy muy confundido ya que después de proporcionar la ubicación, ¿cómo proporciono la imagen real que se debe mostrar en esa posición?
Gracias
ACTUALIZAR:
resultsSize
contiene el tamaño de la matriz de fuentes de datos, self.results
, antes de que se agreguen nuevos datos a partir de los datos en newImages
.
[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];
Consulte Insertar, eliminar y mover secciones y elementos de la " Guía de programación de vista de colección para iOS ":
Para insertar, eliminar o mover una sola sección o elemento, debe seguir estos pasos:
- Actualice los datos en su objeto fuente de datos.
- Llame al método apropiado de la vista de colección para insertar o eliminar la sección o el elemento.
Es fundamental que actualice su fuente de datos antes de notificar a la vista de colección de cualquier cambio. Los métodos de vista de colección suponen que su fuente de datos contiene los datos actualmente correctos. De lo contrario, la vista de recopilación podría recibir un conjunto incorrecto de elementos de su fuente de datos o pedir elementos que no están allí y bloquear su aplicación.
Entonces, en su caso, primero debe agregar una imagen al origen de datos de la vista de colección y luego llamar a insertItemsAtIndexPaths
. La vista de colección pedirá a la función de delegado de fuente de datos que proporcione la vista para el elemento insertado.
Estaba enfrentando el problema similar al eliminar el elemento del índice y esto es lo que creo que tenemos que hacer al usar el método performBatchUpdates:
.
1 # first invoque deleteItemAtIndexPath para eliminar el elemento de la vista de colección.
2 # Eliminar el elemento de la matriz.
3 # Actualizar vista de colección recargando datos.
[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];
}];
Esto me ayuda a eliminar todos los fallos de bloqueo y aserción.