Domanda

Ho un UICollectionView che sto cercando di inserire gli oggetti in esso dinamicamente / con animazione.Quindi ho qualche funzione che scarica le immagini in modo asincrono e vorrei inserire gli elementi in lotti.

Una volta che ho i miei dati, vorrei fare quanto segue:

[self.collectionView performBatchUpdates:^{
    for (UIImage *image in images) {
        [self.collectionView insertItemsAtIndexPaths:****]
    }
} completion:nil];
.

Ora al posto del ***, dovrei passare una matrice di NSIndexPaths, che dovrebbe indicare la posizione dei nuovi articoli da inserire.Sono molto confuso da allora dopo aver fornito la posizione, come posso fornire l'immagine effettiva che dovrebbe essere visualizzata in quella posizione?

Grazie


.

Aggiornamento:

resultsSize contiene la dimensione dell'array della sorgente dati, self.results, prima che i nuovi dati vengano aggiunti dai dati su 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];
.

È stato utile?

Soluzione

Vedi Inserimento, cancellazione e sezioni mobili e elementi da" Guida alla programmazione Visualizzazione della raccolta per iOS ":

.

Per inserire, eliminare o spostare una singola sezione o elemento, è necessario seguire Questi passaggi:

    .
  1. Aggiorna i dati nell'oggetto origine dati.
  2. Chiamare il metodo appropriato della visualizzazione della raccolta per inserire o eliminare la sezione o l'elemento.

    è fondamentale aggiornare la tua origine dati prima di notificare il Vista di raccolta di eventuali modifiche. I metodi di visualizzazione della raccolta assumono che la tua origine dati contiene i dati attualmente corretti. Se lo fa no, la vista di raccolta potrebbe ricevere la serie sbagliata di elementi da la tua origine dati o chiedi elementi che non sono lì e crash il tuo App.

    Allora nel tuo caso, è necessario aggiungere un'immagine alla sorgente dati di visualizzazione della raccolta e quindi chiamare insertItemsAtIndexPaths. La vista di raccolta chiederà quindi la funzione Delegato della sorgente dati per fornire la visualizzazione per l'elemento inserito.

Altri suggerimenti

Ho appena implementato che con Swift.Quindi vorrei condividere la mia implementazione. Prima inizializzare una serie di nsbloccooperazioni:

    var blockOperations: [NSBlockOperation] = []
.

nel controller cambierà, re-init the array:

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    blockOperations.removeAll(keepCapacity: false)
}
.

Nel metodo di modifica dell'oggetto ha fatto:

    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!])
                }
            })
        )
    }
}
.

Nella sezione modificata ha fatto il metodo:

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))
                }
            })
        )
    }
}
.

E infine, nel controller ha cambiato il metodo di contenuto:

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)
    })
}
.

Ho aggiunto personalmente un codice nel metodo Deinit, al fine di cancellare le operazioni quando il ViewController sta per ottenere un deallocato:

deinit {
    // Cancel all block operations when VC deallocates
    for operation: NSBlockOperation in blockOperations {
        operation.cancel()
    }

    blockOperations.removeAll(keepCapacity: false)
}
.

Mi trovavo di fronte al problema simile durante l'eliminazione dell'elemento dall'indice e questo è ciò che penso che dobbiamo fare mentre utilizzeremo il metodo performBatchUpdates:.

1 # PRIMA Chiamata DeleteIteMatIndexPath per eliminare la voce dalla visualizzazione della raccolta.

2 # Elimina l'elemento da array.

3 # Visualizzazione della raccolta aggiornamenti ricaricando i dati.

[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];
        }];
.

Questo aiutami a rimuovere tutti gli errori di crash e asserzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top