2009-09-26 3 views
19

Sto tentando di fare in modo che la mia vista tabella ricordi che è l'ultima posizione, in modo che dopo che l'app viene eseguita di nuovo, scorrerà fino a quella posizione. per fare questo, nel mio metodo viewWillDisappear:, ottengo il primo numero di riga visibile e lo salgo su NSUserDefaults. quindi nel mio viewDidAppear provo a scorrere fino a quella riga inviando scrollToRowAtIndexPath alla visualizzazione tabella. Tuttavia ho un NSRangeException:UITableView scrollToRowAtIndexPath

*** Terminating app due to uncaught exception 'NSRangeException', reason: '-[UITableView scrollToRowAtIndexPath:atScrollPosition:animated:]: section (0) beyond bounds (0).

alcun aiuto apprezzato. Ecco il codice:

- (void)viewDidAppear:(BOOL)animated 
{ 
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 

    if ([userDefaults valueForKey:@"content_row"] != nil) 
    { 
     int rowToHighlight = [[userDefaults valueForKey:@"content_row"] intValue]; 
     NSIndexPath * ndxPath= [NSIndexPath indexPathForRow:rowToHighlight inSection:0]; 
     [contentTableView scrollToRowAtIndexPath:ndxPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; 
    } 
} 

-(void) viewWillDisappear:(BOOL)animated 
{ 
    NSIndexPath *selectedRowPath = [[contentTableView indexPathsForVisibleRows] objectAtIndex:0]; 
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 
    [userDefaults setInteger:selectedRowPath.row forKey:@"content_row"]; 
} 
+0

Potresti postare il bit di codice che crea scrollToRowAtIndexPath e NSIndexPath? – probablyCorey

risposta

52

Ricarica tabella Visualizza i dati prima di chiamare scrollToRowAtIndexPath.

[contentTableView reloadData]; 
+4

Questo non funziona per me quando i dati non sono ancora stati caricati (utilizzando un controller dei risultati recuperato). La mia soluzione era controllare 'tableView.numberOfRowsInSection (0)> 0' prima. – SimplGy

+0

o se su un thread diverso, prova questo. '[tblView performSelectorOnMainThread: @selector (reloadData) withObject: nil waitUntilDone: YES]' – matrixugly

8

È possibile che contentTableView non abbia ancora finito di caricare i dati.

+1

Come posso ricevere una notifica al termine? –

+2

Spiacente, ho pensato che lo scrollToRowAtIndexPath fosse chiamato in viewDidLoad. Ho chiamate simili in viewDidAppear ma, invece di tornare a un numero di riga salvato, torno a un valore di chiave salvato che viene salvato in didSelectRowAtIndexPath. Prima di chiamare scrollToRowAtIndexPath, trovo la riga del valore chiave nell'origine dati attualmente caricata. – DyingCactus

+0

Dolce! Questo in realtà mi ha aiutato a far girare le mie marce nella giusta direzione. Ho elaborato una risposta separata. – matrixugly

0

Voglio approfondire la risposta di DyingCactus. Sono una bella nuovo sviluppatore iOS e la mia situazione era un po 'diverso, ma come ha detto

"E' possibile che il contentTableView non ha ancora carico finito i dati"

Mentre la risposta era breve, mi girava le ruote ed era esattamente quello che stava succedendo per me.

mio Setup

  • UITableView è in ViewController "A"
  • mia app presenta una nuova "B" ViewController
  • On ViewController "B" un pulsante, quindi si aggiunge dati alla fonte di dati per UITableView.
  • Da gestore scatto del tasto di B, [tableView reloadData] si chiama
  • Da gestore scatto del tasto di B, [tableView selectRowAtIndexPath:idxPath animated:false scrollPosition:UITableViewScrollPositionTop]; si chiama
  • ViewController "B" è respinto e "A" si presenta ancora una volta (che mostra la versione aggiornata di UITableView)

Soluzione

  • Il primo problema che ho dovuto risolvere è stato quello di chiamare reloadData sul thread principale come

    [tblView performSelectorOnMainThread: @selector (reloadData) withObject: nil waitUntilDone: false];

  • L'ultimo problema era di cambiare waitUntilDone in true (DUH!)

Sì, quindi ovviamente per me, la contentTableView non è stato fatto il caricamento dei dati, perché la mia chiamata reloadData che viene eseguito sul thread principale non è stato impostato in modo esplicito di bloccare fino a quando è stato fatto il selettore.

Spero che questo aiuti qualcuno.