2009-09-24 4 views
32

Vorrei che il mio UITableView si comportasse come la tabella nell'editor Contatti, cioè l'utente dovrebbe premere Modifica e una riga "aggiungi nuova categoria" dovrebbe apparire nella parte inferiore di ogni sezione.Utilizzo di righe di inserimento in un UITableView

Sto usando il codice qui sotto per fare questo, ma il problema è che non c'è transizione graduale come c'è in Contatti. Invece, la nuova riga appare all'improvviso. Come posso ottenere l'animazione?

Inoltre, come faccio a rispondere ai clic sulla riga "aggiungi nuova categoria"? La riga non è selezionabile nella mia attuale implementazione.

Devo ricaricare i dati quando l'utente inizia a modificare? Lo sto facendo perché altrimenti le righe di inserimento non vengono mai disegnate.

Grazie.

- (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

Questo è stato molto utile (insieme con la risposta, di seguito). Solo una incoerenza minore: il confronto con il conteggio delle righe in 'tableView: cellForRowAtIndexPath:' utilizza '> =' mentre quello in 'tableView: editingStyleForRowAtIndexPath:' utilizza '=='. Non è un grosso problema, ma dovrebbe essere coerente tra loro. '> =' coprirebbe ogni accidentale aggiunta doppia della riga di inserimento, mentre '==' sarebbe di aiuto lanciando un'eccezione per qualsiasi errore di codice che potrebbe portare a quella situazione. –

risposta

36

Mi mancava una cosa. In setEditing :, invece di chiamare reloadData avrei fatto:

- (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

Grazie Bill, mi è stato molto utile. Ho passato parecchie ore a chiacchierare in codice simile ma non riuscivo a farlo nel modo giusto. Ciò ha aiutato incommensurabilmente. – hkatz

+0

Felice di averlo aiutato! – Bill

+0

E riguardo commitEditingStyle: forRowAtIndexPath? La documentazione di Apple dice che setEditing viene chiamato quando la vista tabella va prima in modalità di modifica ... Come sapresti quali righe inserire/eliminare a quel punto? – shim

5

rispondere ai click sulla riga potrebbe essere fatto nel metodo didSelectRowAtIndexPath, per indexPath.row == [items count]. Per l'animazione, suggerisco di dare un'occhiata a here, al metodo insertRowsAtIndexPaths:withRowAnimation:. C'è un post su come usarlo here.

0

Un effetto collaterale indesiderato della soluzione evidenziata è che il "aggiungono" riga viene inserita anche quando l'utente fa scorrere solo una singola riga (purché strisciata è abilitato). Il seguente codice risolve questo dilemma:

// 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; 
} 

Il codice richiederebbe un piccolo cambiamento:

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