Dla prostego przykładu użycia NSMutableArray ciągów nazywanych wierszami, co muszę zaimplementować w moim kontrolerze tabeli, aby przenieść wiersze tableView i odzwierciedlić zmiany w mojej tablicy?Jakie metody muszę zastosować, aby ponownie rozmieścić wiersze UITableView?
Odpowiedz
Tutaj robimy nasze ciężkie podnoszenie.
- (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]);
}
Ponieważ jest to podstawowy przykład, pozwól, aby wszystkie wiersze były ruchome.
- (BOOL)tableView:(UITableView *)tableView
canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
NSMutableArray
ma metodę zwaną exchangeObjectAtIndex:withObjectAtIndex:
.
Próbowałem tego, ale zachowanie jest inne.Tabela nie wymienia rzędów, usuwa jeden wiersz, a następnie wstawia go w innym miejscu. Jeśli skorzystam z tej metody, stół i sklep podkładowy będą bardziej niezsynchronizowane z każdym ruchem. –
Żadne z powyższych nie zadziała. W oryginalnym opublikowanym kodzie widok tabeli ulegnie awarii, ponieważ usunie dane, które będą nadal w użyciu, a nawet po ich skorygowaniu, tablica nie będzie miała poprawnych danych ze względu na sposób, w jaki tabela "przestawia się".
exchangeObjectAtIndex: withObjectAtIndex: nie będzie działać na rozmieszczanie tablicę według jak tableview realizuje własny rozmieszczanie
Dlaczego? Ponieważ gdy użytkownik wybierze komórkę tabeli, aby zmienić jej kolejność, komórka NIE zostanie zamieniona z komórką, do której jest przenoszona. Wybrana komórka zostanie wstawiona do indeksu nowego wiersza, a następnie oryginalna komórka zostanie usunięta. Przynajmniej tak wygląda dla użytkownika.
Rozwiązanie: Ze względu na sposób, w jaki widok stołu implementuje przegrupowanie, musimy wykonać kontrolę, aby upewnić się, że dodaliśmy i usunięto prawy wiersz. Ten kod, który zestawiłem, jest prosty i działa idealnie dla mnie.
Korzystanie z oryginalnych danych kodu jako przykład:
- (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)];
}
}
Jeśli wziąć kilka chwil i przyjrzeć się temu, co dzieje się z tableview podczas Przegrupuj będzie zrozumieć, dlaczego dodajemy 1 gdzie my zrobił.
Jestem całkiem nowy w Xcode, więc wiem, że jest prawdopodobnie łatwiejszy sposób na zrobienie tego, lub kod może być prawdopodobnie uproszczony ... Po prostu próbuję pomóc gdzie mogę, ponieważ zajęło mi to kilka godzin, aby to zrozumieć. Mam nadzieję, że to kogoś oszczędza!
Według dokumentacji Apple i własnego doświadczenia, to jest jakiś prosty kod, który działa całkiem dobrze:
NSObject *tempObj = [[self.rows objectAtIndex:fromIndexPath.row] retain];
[self.rows removeObjectAtIndex:fromIndexPath.row];
[self.rows insertObject:tempObj atIndex:toIndexPath.row];
[tempObj release];
Dobra odpowiedź. Twój jest najbardziej poprawny ze wszystkich. Dzięki! – GeneCode
Znaleziony tę dyskusję po zerwaniu głowę na prostą realizację ... rozwiązanie jest Michael Berding najlepiej dla mnie, na sposób Apple, pamiętaj tylko, aby usunąć zachować i zwolnić podczas korzystania z ARC. Tak więc, bardziej zwięzły rozwiązanie
NSObject *tempObj = [self.rows objectAtIndex:fromIndexPath.row];
[self.rows removeObjectAtIndex:fromIndexPath.row];
[self.rows insertObject:tempObj atIndex:toIndexPath.row];
Kiedy removeObjectAtIndex nazywa, będzie to zmniejszyć liczbę odwołań danego obiektu (a może spowodować, że być zwalniane)? Myślę, że obiekt exchangeObjectAtIndex: withObjectAtIndex: (zgodnie z sugestią @dreamlax) jest bezpieczniejszy. –
BTW, jeśli odpowiadasz na własne pytanie, myślę, że to jest dobra forma, aby zrobić z niego wiki. –
@KristopherJohnson 'exchangeObjectAtIndex: withObjectAtIndex:' nie nadaje się w tym przypadku. Ma inną semantykę niż te wymagane przez 'tableView: moveRowAtIndexPath: toIndexPath:'. – Benjohn