7 Stimmen

UITableView insertSections: withRowAnimation: alle Tabellenzellen werden angefordert

Ich arbeite daran, einen bestehenden, schwerfälligen Code zu ändern, der einfach die [tableView reloadData] bei jeder Änderung, bis hin zur Verwendung spezifischerer Tabellenaktualisierungen mit den Insert/Delete-Methoden.

Allerdings habe ich dabei ein wirklich schlechtes Verhalten. Bisher wurden, wie man sich vorstellen kann, beim Laden der Tabelle nur Zellen für die Zeilen angefordert, die zu diesem Zeitpunkt sichtbar waren. Dies war das Verhalten, wenn reloadData verwendet wurde.

Nun, da insertSections aufgerufen wird, 何れも Zellen nach dieser Aktualisierung angefordert werden, was Hunderte sein können. Dies führt dazu, dass Zellen für jede Zeile erstellt werden, was die Warteschlange für wiederverwendbare Zellen völlig ruiniert und einfach nur verschwenderisch ist. I doit etwas falsch machen.

Die Änderung ist dieser einfache Code, der dazu führt, dass die tableView nur nach sichtbaren Zeilen fragt:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    // ... ensure it's the right key
    [tableView reloadData];
}

Code, der dazu führt, dass die tableView nach allem fragt:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    // ... ensure it's the right key
    NSUInteger sectionCount = [self sectionCount];
    NSIndexSet *indices = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)];
    [tableView insertSections:indices withRowAnimation:UITableViewRowAnimationFade];
}

Ich kann hin und her schalten, um zu sehen, wie sich das Verhalten ändert. Frustrierend. Haben Sie eine Idee?


Ich setze ein Kopfgeld aus, nur um zu sehen, ob jemand weitere Erkenntnisse hat.

Die beginUpdates/endUpdates beeinflussen nichts, und ich würde nicht erwarten, dass es, dies ist nur ein Befehl, es gibt nichts extra zu einer einzigen Aktualisierung zu verschmelzen.

Ich denke, das ist einfach ein Nebeneffekt des Wunsches nach der Animation. Um alles "einschieben" zu können, muss es alles gerendert werden. Game over.

6voto

Louis Gerbarg Punkte 43196

Es scheint, als würden Sie die Tabelle anweisen, alle Abschnitte einzufügen, was im Grunde genommen einem Neuladen gleichkommt. Wenn Sie der Tabelle sagen, dass sie einen Abschnitt laden soll, muss sie alle Elemente in diesem Abschnitt lesen. Außerdem tun Sie es außerhalb eines beginUpdates/endUpdates-Blocks, was bedeutet, dass jedes Mal, wenn Sie den Abschnitt hinzufügen, die Tabelle die Änderungen sofort festschreiben muss. Wenn Sie alles in einen beginUpdates/endUpdates-Block einschließen, werden alle Abfragen ausgesetzt, bis sie abgeschlossen sind, wodurch das System redundante Abfragen zusammenfassen und Abfragen eliminieren kann, die sich als nicht notwendig erweisen.

Sie sollten insertSections nur aufrufen, wenn neue Abschnitte hinzugefügt werden. Wenn Sie das tun, muss tableview nicht die Informationen aller unveränderten Abschnitte abfragen, selbst wenn sie sich verschieben. Wenn sich Elemente innerhalb eines Abschnitts ändern, der Abschnitt selbst jedoch nicht, sollten Sie die Zeilenversion der Methoden verwenden, um diese spezifischen Zeilen innerhalb des Abschnitts zu ändern, und nur diese Zeilen werden abgefragt.

Nachfolgend finden Sie ein Beispiel (aus einer CoreData-basierten Anwendung), das den Sinn des Ganzen verdeutlichen soll. Da Sie ein benutzerdefiniertes Modell anstelle eines NSFetchedResultsController haben, müssen Sie die Art der Aktion herausfinden, anstatt nur eine Reihe von Konstanten zu überprüfen, die Ihnen vom System übergeben werden.

//Calculate what needs to be changed     

[self.tableView beginUpdates];

for (i = 0 i < changeCount; i++) {
  type = changes[i]; 

  switch(type) {
    case NSFetchedResultsChangeInsert:
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                    withRowAnimation:UITableViewRowAnimationFade];
      break;

    case NSFetchedResultsChangeDelete:
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                    withRowAnimation:UITableViewRowAnimationFade];
      break;
  }
}

switch(type) {

  case NSFetchedResultsChangeInsert:
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                          withRowAnimation:UITableViewRowAnimationFade];
    break;

  case NSFetchedResultsChangeDelete:
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                          withRowAnimation:UITableViewRowAnimationFade];
    break;

  case NSFetchedResultsChangeUpdate:
    [self configureCell:(id)[tableView cellForRowAtIndexPath:indexPath]
            atIndexPath:indexPath];
    break;

  case NSFetchedResultsChangeMove:
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                          withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section]
                  withRowAnimation:UITableViewRowAnimationFade];
    break;
  }
}

[self.tableView endUpdates];

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X