Domanda

La documentazione per NSFetchedResultsControllerDelegate fornire il seguente codice di esempio

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            break;

    }

}

Quando creo un nuovo NSManagedObject, NSFetchedResultsChangeInsert incendi (grandi!). Quando cambio il valore di un attributo (utilizzato per il titolo della cellula), NSFetchedResultsChangeUpdate incendi. Purtroppo, il nuovo titolo non visualizza automaticamente a meno che non ricaricare la tabella, la sezione o una riga. Infatti, se il nuovo nome provoca il set di risultati di ordinamento diverso, allora NSFetchedResultsChangeMove incendi e tutto è bene in quanto il codice fornito ricarica l'intera sezione.

UITableView ha un metodo reloadRowsAtIndexPaths: withRowAnimation quindi provato utilizzando questo sotto la NSFetchedResultsChangeUpdate blocco di codice. E 'effettivamente funziona ... ma la documentazione di questo metodo specifico letto come se io non ne ho bisogno (notate l'ultima riga):

  

RICARICA una riga provoca la   vista tabella per chiedere la sua fonte di dati per   una nuova cella per quella riga. La tavola   anima che nuova cella in quanto   anima la riga vecchia fuori. chiamare questo   metodo se si desidera avvertire l'utente   che il valore di una cella cambia.   Se, tuttavia, notificare l'utente non è   importante, cioè, si vuole solo   modificare il valore che una cellula è   visualizzazione-è possibile ottenere il cellulare per un   particolare riga e impostare il nuovo valore.

E sì, se accedo ciò che sta accadendo, quando

[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 

viene invocata su un NSFetchedResultsChangeUpdate , è in grado di recuperare il valore più recente 'nome' e metterlo in textLabel della cellula. Il nome non è solo il rendering nella cella a meno che non ricaricarlo. Anche se ho semplicemente fare clic sulla cella il nome si presenta. Si noti che per ricreare questo comportamento, è necessario creare un nuovo oggetto gestito e poi dargli un nome che induce a ordinare FIRST nel NSFetchedResultsController. In questo modo, il NSFetchedResultsChangeMove non si attiva (che non funziona poiché ricarica la sezione).

Mi sto perdendo qualcosa o si tratta di comportamento previsto? Il 'discussione' per reloadRowsAtIndexPaths mi porta a credere che dovrei essere in grado di impostare semplicemente textLabel della cella senza ricaricare la riga, sezione o tavolo.

È stato utile?

Soluzione

Si dovrebbe chiamare [cell setNeedsLayout] o / e [cell setNeedsDisplay] a causare la cellula per ottenere rinfrescato, a seconda dell'implementazione del tuo cellulare.

Se si compone la cella di subviews come siamo soliti fare, che si basano su - layoutSubviews, così si dovrebbe chiamare [cell setNeedsLayout].

Se si disegna la cella direttamente con – drawRect:, si dovrebbe chiamare [cell setNeedsDisplay].

Se si utilizza sia la composizione e il disegno, si dovrebbe chiamare entrambi.

Altri suggerimenti

Mentre è vero che non è necessario ricaricare il cellulare in modo da avere i cambiamenti avvengono, si deve ricordare che le cache iPhone vista del disegno, per quanto possibile. Una volta che avete appena configurato il vostro cellulare, è necessario chiamare setNeedsDisplay sulla cella al fine di innescare il ridisegno.

Anche se non è stato esplicitamente affermato, che hai effettivamente avuto modo di fare in modo di includere i metodi delegato per controllerWillChangeContent: e controllerDidChangeContent:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}

e

- (void)controllerDidChangeContent:(BSFetchedResultsController *)controller {
    @try {
        [self.tableView endUpdates];
    }
    @catch (NSException * e) {
        NSLog(@"caught exception: %@: %@", [e name], [e description]);
    }
    @finally { }
}

Il NSFRC può sparare controller multipli: didChangeObject: atIndexPath: forChangeType: newIndexPath: metodi in qualsivoglia modifica, quindi non aspettatevi la riga della tabella per modificare subito dopo ciascuno di questi. Faranno solo aggiornamento si chiama endUpdates sul tavolo.

Chiamare la logica di aggiornamento dell'interfaccia utente nel thread principale Ha risolto il problema (sia [cell setNeedsLayout] & [cell setNeedsDisplay] non funziona per me):

...
case NSFetchedResultsChangeUpdate:
    dispatch_async(dispatch_get_main_queue(), {
      [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
    });
    break;
...

Cosa c'è di più (non su questo problema, ma sarà utile), è meglio scegliere di utilizzare il newIndexPath se è disponibile:

...
case NSFetchedResultsChangeUpdate:
    dispatch_async(dispatch_get_main_queue(), {
      NSIndexPath * targetIndexPath = (newIndexPath ?: indexPath)
      [self configureCell:[tableView cellForRowAtIndexPath:targetIndexPath]
              atIndexPath:targetIndexPath];
    });
    break;
...
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top