2009-09-24 8 views
32

Chciałbym, aby mój UITableView zachowywał się jak tabela w edytorze Kontakty, tj. Użytkownik powinien nacisnąć Edytuj, a wiersz "dodaj nową kategorię" powinien pojawić się u dołu każdej sekcji.Używanie wstawiania wierszy w UITableView

Używam do tego poniższego kodu, ale problem polega na tym, że nie ma płynnego przejścia, jak w Kontakty. Zamiast tego nagle pojawia się nowy wiersz. Jak mogę uzyskać animację?

Co należy zrobić, aby odpowiedzieć na kliknięcia wiersza "dodaj nową kategorię"? Wiersz nie jest klikalny w mojej obecnej wersji.

Czy muszę ponownie załadować dane, gdy użytkownik rozpocznie edycję? Robię to, ponieważ w przeciwnym razie wiersze wstawiania nigdy nie zostaną narysowane.

Dzięki.

- (void)setEditing:(BOOL)editing animated:(BOOL)animated { 
    [super setEditing:editing animated:animated]; 
    [self.tableView setEditing:editing animated:animated]; 
    [tableView reloadData]; 
} 

- (NSInteger)tableView:(UITableView *)_tableView numberOfRowsInSection:(NSInteger)section { 
    // ... 
    if(self.tableView.editing) 
     return 1 + rowCount; 
} 

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    // ..... 
    NSArray* items = ...; 
    if(indexPath.row >= [items count]) { 
     cell.textLabel.text = @"add new category"; 
    } 
    // ... 

    return cell; 
} 

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSArray* items = ...; 

    if(indexPath.row == [items count]) 
     return UITableViewCellEditingStyleInsert; 

    return UITableViewCellEditingStyleDelete; 
} 
+2

To był bardzo pomocny (wraz z odpowiedzią poniżej). Tylko jedna niewielka niespójność - porównanie z liczbą wierszy w 'tableView: cellForRowAtIndexPath:' używa '> =' podczas gdy w 'tableView: editingStyleForRowAtIndexPath:' używa '=='. Nic wielkiego, ale powinna być zgodna między nimi. '> =' obejmuje przypadkowe podwójne dodanie wiersza Insert, a '==' pomogłoby rzucając wyjątek dla wszelkich błędów kodu, które mogłyby doprowadzić do takiej sytuacji. –

Odpowiedz

36

Brakowało mi jednej rzeczy. W setEditing :, zamiast dzwonić reloadData powinienem zrobić:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated { 
    [super setEditing:editing animated:animated]; 
    [self.tableView setEditing:editing animated:animated]; // not needed if super is a UITableViewController 

    NSMutableArray* paths = [[NSMutableArray alloc] init]; 

    // fill paths of insertion rows here 

    if(editing) 
     [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom]; 
    else 
     [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom]; 

    [paths release]; 
} 
+3

Dzięki Bill, to było dla mnie bardzo przydatne. Spędziłem kilka godzin, grzebiąc w podobnym kodzie, ale nie mogłem tego naprawić. Pomogło to niezmiernie. – hkatz

+0

Cieszę się, że pomogło! – Bill

+0

co o commitEditingStyle: forRowAtIndexPath? Dokumentacja Apple mówi, że setEditing jest wywoływane, gdy widok tabeli przechodzi najpierw do trybu edycji ... Skąd wiesz, jakie wiersze wstawiać/usuwać w tym momencie? – shim

5

odpowiedzi na kliknięcia w rzędzie może być wykonane w sposób didSelectRowAtIndexPath na indexPath.row == [items count]. W przypadku animacji sugeruję przyjrzeć się metodzie here przy metodzie insertRowsAtIndexPaths:withRowAnimation:. Jest post, jak go używać. here.

0

niepożądany efekt uboczny wyróżnionego rozwiązania jest to, że „dodatek” rząd dodaje się również wtedy, gdy użytkownik po prostu przejeżdża jeden pojedynczy wiersz (pod warunkiem, że przesuwając jest włączony). Poniższy kod rozwiązuje ten dylemat:

// Assuming swipeMode is a BOOL property in the class extension. 

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // Invoked only when swiping, not when pressing the Edit button. 
    self.swipeMode = YES; 
} 

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    self.swipeMode = NO; 
} 

Twój kod będzie wymagać małej zmiany:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated { 
    [super setEditing:editing animated:animated]; 
    [self.tableView setEditing:editing animated:animated]; // not needed if super is a UITableViewController 

    if (!self.swipeMode) { 

     NSMutableArray* paths = [[NSMutableArray alloc] init]; 

     // fill paths of insertion rows here 

     if(editing) 
      [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom]; 
     else 
      [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom]; 
     [paths release]; 
    } 
} 
Powiązane problemy