2012-07-17 17 views
5

Ho creato un UITableview con sezioni selezionabili. Quando si fa clic su di essi,insertRowsAtIndexPaths: con scrollToRowAtIndexPath: le sezioni di UITableView sono nascoste in modo errato

  1. che "espandono" per rivelare le cellule al loro interno
  2. i rotoli sezione cliccato per la parte superiore della vista.

ho calcolare tutti i indexpaths per inserire/eliminare le cellule necessarie e poi inserirli con il seguente codice:

[self.tableView beginUpdates]; 
[self.tableView insertRowsAtIndexPaths:pathsToOpen withRowAnimation:insertAnimation]; 
[self.tableView deleteRowsAtIndexPaths:pathsToClose withRowAnimation:deleteAnimation]; 
[self.tableView endUpdates]; 
[self.tableView scrollToRowAtIndexPath:[pathsToOpen objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES]; 

C'è solo un problema-sezioni sotto la sezione selezionata sono nascosti. La prima schermata mostra come dovrebbe apparire la vista tabella. La seconda schermata mostra come effettivamente appare.

Sections Disappear

Se si scorre verso l'alto (in modo che le sezioni nascoste sono fuori campo) e quindi scorrere verso il basso, le sezioni nascoste sono riportati (ancora una volta visibile). La mia ipotesi sul perché ciò stia accadendo è la seguente:

Le animazioni di inserimento/eliminazione si verificano contemporaneamente allo scrollToRowAtIndexPath e confonde il TableView. Se non avessi fatto le sezioni 4 sarebbe stato disattivato - e quindi il TableView in qualche modo pensa ancora che siano fuori schermo. UITableview nasconde le celle/sezioni che sono offscreen come ottimizzazione. Se chiamo scrollToRowAtIndexPath con un dispatch_after con 2 secondi, le sezioni 3 & 4 vengono visualizzate correttamente.

Quindi penso di sapere perché questo sta accadendo, ma non so come risolvere/sovrascrivere l'ottimizzazione di UITableview. In realtà, se implemento scrollViewDidEndScrollingAnimation e poi aggiungo un punto di interruzione in questa funzione, l'app visualizza correttamente le sezioni 3 & 4 (è così che ho ottenuto la prima schermata). Ma una volta che si continua da questa funzione, le cellule scompaiono.

Il progetto completa può essere scaricata here


Ulteriori dettagli di implementazione: le sezioni sono sezioni UITableView legittimi. Ho aggiunto un tapGestureRecognizer che attiva una chiamata delegata al tableview. Di seguito è incluso l'intero metodo che apre le sezioni.

+0

Penso che sia meglio usare l'MVC fornito da Apple. Tutto quello che devi fare è aggiungere/rimuovere i dati nella tua origine dati e non toccare le righe della vista tabella – divol

+0

Per favore includi un po 'più del tuo progetto nella domanda, piuttosto che aspettarti un download - per esempio, come calcoli i percorsi dell'indice aggiungere/rimuovere e sono le intestazioni della sezione "sezione X" delle cose o sono solo celle? Sarebbe una domanda autonoma migliore se non dipendesse così tanto dal download del tuo progetto. – jrturton

+0

Penso che anche la tua ipotesi sia giusta. Puoi provare a ricaricare le righe con il metodo di delega a scorrimento terminato? – jrturton

risposta

6

Da quello che posso dire, il problema si verifica quando si restituisce una vista di sezione che è già stata utilizzata. Invece di:

- (UIView *)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section 
{ 
    return [self.sectionHeaderViews objectAtIndex:section]; 
} 

ho alcun problema se creo una nuova visione ogni volta:

- (UIView *)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section{ 
    SectionHeaderView *sectionHeaderView = [self.tableView dequeueReusableCellWithIdentifier:SectionHeaderView_NibName]; 
    sectionHeaderView.textLabel.text = [NSString stringWithFormat:@"Section %d", section]; 

    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:sectionHeaderView action:@selector(handleTap:)]; 
    [sectionHeaderView addGestureRecognizer:tapRecognizer]; 
    sectionHeaderView.section = section; 
    sectionHeaderView.delegate = self; 
    return sectionHeaderView; 
} 

E 'possibile questo sta accadendo perché si sta utilizzando [self.tableView dequeueReusableCellWithIdentifier:SectionHeaderView_NibName]; per creare intestazioni di sezione e tenere su di loro in un array, che non penso sia stato creato per UITableViewCell, ma non ne sono sicuro. Puoi prendere in considerazione l'ipotesi di rinunciare a UITableViewCell per le viste di sezione e invece usare qualcos'altro (magari un UIImageView con un UILabel). Oppure non puoi semplicemente archiviare le viste in sezione in un array ... nel modo in cui hai attualmente impostato il codice, non hai bisogno dell'array e creare una nuova vista è abbastanza banale da non doverti preoccupare.

4

@ opere risposta di AaronHayman (e IMO l'accetta e la generosità dovrebbe andare da lui, così com'è - questo proprio non si adattava in un commento), ma vorrei andare oltre - non si dovrebbe usare una cella per l'intestazione di sezione, e non dovresti usare il meccanismo di dequeue per caricare essenzialmente un pennino.

Le sezioni di intestazione di sezione non dovrebbero essere celle, e si possono ottenere effetti indesiderati usandoli al posto di viste regolari, in particolare se sono deqeueued - la tabella mantiene un elenco di queste celle riutilizzabili quando lo si fa e li ricicla quando escono dallo schermo, ma le intestazioni delle sezioni non sono riutilizzabili, ne esiste una per sezione.

Nel progetto di esempio, ho cambiato la superclasse di SectionHeaderView essere un UIView pianura, e cambiato il metodo di createSectionHeaderViews per caricare direttamente dai pennini lì:

NSMutableArray *sectionHeaderViews = [[NSMutableArray alloc] init]; 
    UINib *headerNib = [UINib nibWithNibName:SectionHeaderView_NibName bundle:nil]; 
    for (int i = 0; i < 5; i++) 
    { 
     SectionHeaderView *sectionHeaderView = [[headerNib instantiateWithOwner:nil options:nil] objectAtIndex:0]; 
     sectionHeaderView.textLabel.text = [NSString stringWithFormat:@"Section %d", i]; 

     UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:sectionHeaderView action:@selector(handleTap:)]; 
     [sectionHeaderView addGestureRecognizer:tapRecognizer]; 
     sectionHeaderView.section = i; 
     sectionHeaderView.delegate = self; 

     [sectionHeaderViews addObject:sectionHeaderView]; 
    } 
    self.sectionHeaderViews = sectionHeaderViews; 

ho anche commentato il registro per la linea riutilizzo dal tuo viewDidLoad. Ciò impedisce la scomparsa delle intestazioni di sezione.

+0

Buona idea mostrargli come istanziare la vista da un pennino. Generalmente creo tutte le mie visualizzazioni in codice, quindi non ci ho nemmeno pensato. –

Problemi correlati