Frage

Ich habe ein UICollectionView was ich versuche, Elemente dynamisch/mit Animation einzufügen.Ich habe also eine Funktion, die Bilder asynchron herunterlädt und möchte die Elemente stapelweise einfügen.

Sobald ich meine Daten habe, möchte ich Folgendes tun:

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

Jetzt anstelle der ***, ich sollte ein Array von übergeben NSIndexPaths, die auf den Speicherort der neuen einzufügenden Elemente verweisen sollte.Ich bin sehr verwirrt, denn wie stelle ich nach der Angabe des Standorts das tatsächliche Bild bereit, das an dieser Position angezeigt werden soll?

Danke


AKTUALISIEREN:

resultsSize enthält die Größe des Datenquellenarrays, self.results, bevor neue Daten aus den Daten hinzugefügt werden 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];
War es hilfreich?

Lösung

Sehen Abschnitte und Elemente einfügen, löschen und verschieben von dem "Collection View-Programmierhandbuch für iOS":

Um einen einzelnen Abschnitt oder Element einfügen, löschen oder verschieben, müssen Sie folgende Schritte befolgen:

  1. Aktualisieren Sie die Daten in Ihrem Datenquellenobjekt.
  2. Rufen Sie die entsprechende Methode der Sammlungsansicht auf, um den Abschnitt oder das Element einzufügen oder zu löschen.

Es ist wichtig, dass Sie Ihre Datenquelle aktualisieren, bevor Sie die Sammelansicht über Änderungen informieren.In den Methoden zur Sammlung der Ansicht geht es davon aus, dass Ihre Datenquelle die aktuell korrekten Daten enthält.Wenn dies nicht der Fall ist, empfängt die Sammelansicht möglicherweise die falsche Reihe von Elementen aus Ihrer Datenquelle oder fragen Sie nach Elementen, die nicht vorhanden sind, und stürmen Ihre App ab.

In Ihrem Fall müssen Sie also zuerst ein Bild zur Datenquelle der Sammlungsansicht hinzufügen und dann aufrufen insertItemsAtIndexPaths.Die Sammlungsansicht fordert dann die Datenquellen-Delegatenfunktion auf, die Ansicht für das eingefügte Element bereitzustellen.

Andere Tipps

Ich habe das gerade mit Swift umgesetzt.Deshalb möchte ich meine Implementierung teilen.Initialisieren Sie zunächst ein Array von NSBlockOperations:

    var blockOperations: [NSBlockOperation] = []

Wenn sich der Controller ändert, initialisieren Sie das Array neu:

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

In der Methode „hat das Objekt geändert“:

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

In der Methode „hat sich geändert“:

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

Und schließlich hat der Controller die Inhaltsmethode geändert:

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

Ich persönlich habe auch etwas Code in die Deinit-Methode eingefügt, um die Vorgänge abzubrechen, wenn der ViewController kurz vor der Freigabe steht:

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

    blockOperations.removeAll(keepCapacity: false)
}

Ich hatte beim Löschen des Elements aus dem Index ein ähnliches Problem, und ich denke, das müssen wir bei der Verwendung tun performBatchUpdates: Methode.

1# Rufen Sie zuerst deleteItemAtIndexPath auf, um das Element aus der Sammlungsansicht zu löschen.

2# Löschen Sie das Element aus dem Array.

3# Aktualisieren Sie die Sammlungsansicht, indem Sie die Daten neu laden.

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

Dies hilft mir, alle Abstürze und Behauptungsfehler zu beseitigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top