Für ein einfaches Beispiel für die Verwendung eines NSMutableArray von Strings namens rows, was muss ich in meinem Tabellen-Controller implementieren, um die tableView-Zeilen zu verschieben und die Änderungen in meinem Array widerzuspiegeln?Welche Methoden muss ich implementieren, um die UITableView-Zeilen neu anzuordnen?
Antwort
Hier machen wir unser schweres Heben.
- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
toIndexPath:(NSIndexPath *)toIndexPath
{
NSLog(@"move from:%d to:%d", fromIndexPath.row, toIndexPath.row);
// fetch the object at the row being moved
NSString *r = [rows objectAtIndex:fromIndexPath.row];
// remove the original from the data structure
[rows removeObjectAtIndex:fromIndexPath.row];
// insert the object at the target row
[rows insertObject:r atIndex:toIndexPath.row];
NSLog(@"result of move :\n%@", [self rows]);
}
Da dies ein einfaches Beispiel ist, lassen Sie alle Zeilen beweglich sein.
- (BOOL)tableView:(UITableView *)tableView
canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
NSMutableArray
hat eine Methode namens exchangeObjectAtIndex:withObjectAtIndex:
.
Ich habe dieses versucht, aber das Verhalten ist anders.Die Tabelle tauscht die Zeilen nicht aus, entfernt eine Zeile und fügt sie an anderer Stelle ein. Wenn ich diese Methode verwende, sind die Tabelle und der Backing Store bei jeder Bewegung nicht mehr synchron. –
Keines der obigen funktioniert. Im ursprünglichen geposteten Code stürzt die Tabellenansicht ab, weil sie die Daten entfernt, die noch verwendet werden, und selbst nachdem sie korrigiert wurden, würde das Array aufgrund der Art und Weise, wie die Tabelle eine 'Neuanordnung' vornimmt, nicht die richtigen Daten haben.
exchangeObjectAtIndex: withObjectAtIndex: ein Array für Neuanordnung nach nicht funktionieren, wie ein Tableview seine eigene implementiert
Warum neu anordnen? Da, wenn der Benutzer eine Tabellenzelle auswählt, um sie neu anzuordnen, wird diese Zelle NICHT mit der Zelle vertauscht, in die sie verschoben wird. Die ausgewählte Zelle wird in den neuen Zeilenindex eingefügt, und anschließend wird die ursprüngliche Zelle entfernt. So sieht es zumindest für den Benutzer aus.
Lösung: Aufgrund der Art, wie die Tabellenansicht eine Neuanordnung implementiert, müssen wir eine Überprüfung durchführen, um sicherzustellen, dass wir die richtige Zeile hinzufügen und entfernen. Dieser Code, den ich zusammensetze, ist einfach und funktioniert perfekt für mich.
die Original geschrieben Codedaten als Beispiel:
- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
toIndexPath:(NSIndexPath *)toIndexPath
{
NSLog(@"move from:%d to:%d", fromIndexPath.row, toIndexPath.row);
// fetch the object at the row being moved
NSString *r = [rows objectAtIndex:fromIndexPath.row];
// checks to make sure we add and remove the right rows
if (fromIndexPath.row > toIndexPath.row) {
// insert the object at the target row
[rows insertObject:r atIndex:toIndexPath.row];
// remove the original from the data structure
[rows removeObjectAtIndex:(fromIndexPath.row + 1)];
}
else if (fromIndexPath.row < toIndexPath.row) {
// insert the object at the target row
[rows insertObject:r atIndex:(toIndexPath.row + 1)];
// remove the original from the data structure
[rows removeObjectAtIndex:(fromIndexPath.row)];
}
}
Wenn Sie ein paar Minuten Zeit nehmen und werfen Sie einen Blick auf, was während eines neu anordnen zu einem Tableview geschieht Sie werden verstehen, warum wir das 1 ist, wo wir hinzufügen hat getan.
Ich bin ziemlich neu zu xcode, also weiß ich, es gibt wahrscheinlich eine einfachere Möglichkeit, dies zu tun, oder der Code kann wahrscheinlich vereinfacht werden .... Nur versuchen, zu helfen, wo ich kann, weil es mich ein paar genommen hat Stunden, um das herauszufinden. Hoffe das spart jemandem etwas Zeit!
Laut Apples Dokumentation, und meine eigene Erfahrung, diese einige einfache Code, der recht gut funktioniert:
NSObject *tempObj = [[self.rows objectAtIndex:fromIndexPath.row] retain];
[self.rows removeObjectAtIndex:fromIndexPath.row];
[self.rows insertObject:tempObj atIndex:toIndexPath.row];
[tempObj release];
Schöne Antwort. Dein ist das Korrekteste von allen. Danke, Mann! – GeneCode
diese Diskussion gefunden, nachdem mein Kopf gegen eine einfache Implementierung zu brechen ... Michael Berding Lösung ist die Am besten für mich, den Apple-Weg, nur daran denken, zu entfernen und zu lösen, wenn Sie ARC verwenden. Also, eine prägnantere Lösung
NSObject *tempObj = [self.rows objectAtIndex:fromIndexPath.row];
[self.rows removeObjectAtIndex:fromIndexPath.row];
[self.rows insertObject:tempObj atIndex:toIndexPath.row];
Wenn removeObjectAtIndex aufgerufen wird, reduziert dies die Referenzanzahl des Objekts (und möglicherweise dazu führen, dass es freigegeben wird)? Ich denke, ExchangeObjectAtIndex: withObjectAtIndex: (wie von @dreamlax vorgeschlagen) ist sicherer. –
BTW, wenn Sie Ihre eigene Frage beantworten, denke ich, es ist gute Form, es zu einem Wiki zu machen. –
@KristopherJohnson 'exchangeObjectAtIndex: withObjectAtIndex:' ist in diesem Fall nicht geeignet. Es hat eine andere Semantik als die von 'tableView: moveRowAtIndexPath: toIndexPath:'. – Benjohn