2012-11-06 8 views
7

Attualmente sto implementando la conservazione/ripristino automatico dello stato in un'app solo iOS6.Strane chiamate a modelIdentifierForElementAtIndexPath: inView: (UIDataSourceModelAssociation)

Per un restauro di una vista tabella, ho aggiunto il protocollo UIDataSourceModelAssociation ai miei controller di vista tavolo e implementato

- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view

e

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view

Quando si preme il tasto home, il i metodi di conservazione dello stato, incluso modelIdentifierForElementAtIndexPath:iView:, vengono richiamati come previsto e restituiscono stringhe di identificatore valido per i percorsi dell'indice specificati.

Quando si uccide l'app e la si riavvia, i lavori di ripristino dello stato sono più o meno. Cioè l'app riapre la vista tabella corretta. Tuttavia, la vista tabella viene sempre spostata verso l'alto, anche se prima era stata spostata in un'altra posizione.

Ecco l'implementazione dei metodi UIDataSourceModelAssociation nel mio controller di visualizzazione tabella. Niente di speciale succedendo in là (la proprietà NdlFriend::accountUid restituisce una stringa identificatore univoco per un determinato record NdlFriend):

#pragma mark - UIDataSourceModelAssociation 
- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view 
{ 
    NSString* identifier = nil; 
    NSArray* content = self.contentArray; 

    // Sometimes idx might be nil... 
    if(idx && idx.row<content.count) 
    { 
     NdlFriend* friend = content[idx.row]; 
     identifier=friend.accountUid; 
    } 
    return identifier; 
} 

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view 
{ 
    NSIndexPath * indexPath=nil; 
    NSArray* content = self.contentArray; 
    NSInteger count = content.count; 
    for(NSInteger i=0;i<count;i++) 
    { 
     NdlFriend* friend = content[i]; 
     if([identifier isEqualToString:friend.accountUid]) 
     { 
      indexPath = [NSIndexPath indexPathForRow:i inSection:0]; 
      break; 
     } 
    } 
    return indexPath; 
} 

ho impostato rompere i punti in entrambi i metodi.

Per testare i metodi, ho aperto la vista tabella e fatto scorrere verso il basso un po '. Quindi, quando si preme il tasto home:

  • modelIdentifierForElementAtIndexPath:inView: viene chiamato una volta, con il percorso dell'indice della riga più visibile in alto. Il metodo restituisce l'uid corretto per questa riga.

Fin qui tutto bene.

Quindi mi fermo e riavvio l'app. Ecco cosa succede (sto soprattutto perplesso il primo punto di interruzione colpo):

  • modelIdentifierForElementAtIndexPath:inView: viene chiamato, con nil come percorso dell'indice (l'argomento vista contiene il corretto puntatore della vista tabella).
  • indexPathForElementWithModelIdentifier:inView: viene chiamato con una stringa di identificatore valida (e il metodo restituisce un percorso indice valido).
  • indexPathForElementWithModelIdentifier:inView: viene chiamato di nuovo (con la stessa stringa di identificatore).
  • La vista tabella viene aggiornata, ma scorre verso l'alto.

Qualcuno sa, perché il ripristino della posizione di scorrimento non riesce? Forse la chiamata di modelIdentifierForElementAtIndexPath:inView: con nil come indexPath ha qualcosa a che fare con esso (o è questo comportamento normale).

+1

Mentre il ripristino della posizione di scorrimento della vista tabella (principalmente) funziona ora in iOS 9, il comportamento interrotto descritto nella domanda dove 'modelIdentifierForElementAtIndexPath: inView:' _gets ha chiamato, con nil come percorso dell'indice_ talvolta si verifica quando una vista tabella vuota è ripristinato, risultando in un'eccezione _bad accesso_. Una soluzione alternativa consiste nel cambiare la firma del metodo per accettare un 'NSIndexPath!' E proteggerlo da 'nil' (restituendo' nil'), anche se ** non dovrebbe mai accadere **! (In alternativa, per evitare l'avvertimento, restituire 'nil' se' numberOfRowsInSection (0) 'è zero funziona anche.) – penfold

risposta

0

Non penso che il problema riscontrato nella posizione di scorrimento della visualizzazione della tabella abbia a che fare con i metodi UIDataSourceModelAssociation.

Credo che ci sia un bug con un controller di visualizzazione tabella incorporato in un controller di navigazione, che lo fa ripristinare la sua posizione di scorrimento dopo il ripristino. A quanto ho capito, se le celle nella visualizzazione tabella non vengono riordinate, non è necessario implementare i metodi UIDataSourceModelAssociation e si dovrebbe ottenere la posizione di scorrimento "gratuitamente" (vale a dire fino a quando si è optato per la conservazione dello stato e impostare gli ID dei restauri). Non posso davvero confermarlo esplicitamente dalla documentazione, salvo sottolineare che UITableView discende da UIScrollView, che salva la sua posizione di scorrimento. Ho verificato che se si imposta il controller di visualizzazione tabella come controller principale o se si incorpora un controller di visualizzazione tabella in un controller barra di tabulazione, la posizione di scorrimento è ripristinata.

Ho archiviato un bug report, dovresti farlo anche tu, se non lo hai già fatto.

1

C'è un bug in iOS 6 per quanto riguarda il ripristino dello stato di Table Visualizzazioni in Controller di navigazione.

Si può vedere il radar aperto qui: rdar://13438788

Come si può vedere, si tratta di un duplicato, così Apple sono consapevoli di questo.

Inoltre, guarda questo link successivo, il tizio che ha pubblicato quel radar aperto ha fatto anche questo post sul blog, ha le soluzioni proposte che gli ingegneri Apple gli hanno detto.

Rende la conservazione/ripristino dello stato per me non una caratteristica così piacevole da implementare, sebbene ricordi, questo è per i tuoi utenti! Quindi dovresti comunque fare il workaround.

Nota: esistono 2 soluzioni alternative, una per le informazioni di visualizzazione della vista tabella da ripristinare (ad esempio scorrimento) e un'altra soluzione alternativa per l'implementazione di UIDataSourceModelAssociation, come nel caso specifico.

http://useyourloaf.com/blog/2013/04/07/bug-table-view-state-not-restored-when-embedded-in-navigation-controller.html

0

Assicurarsi che non si sta eseguendo un recupero asincrono sui dati. Se stai recuperando i tuoi dati da viewDidLoad, assicurati di utilizzare una chiamata [myManagedObjectContext performBlockAndWait:^{}] invece di un [myManagedObjectContext performBlock:^{}].

È possibile che si disponga di una condizione di competizione in cui self.contentArray è vuoto quando viene chiamato indexPathForElementWithModelIdentifier.

Problemi correlati