6

Ich habe eine UITabbar mit mehreren Controllern drin. Einer der Controller wird zum Hinzufügen von Ereignissen zu Core Data verwendet, während ein anderer Controller zum Anzeigen von Ereignissen wie in einer UITableView mit NSFetchedResultsController verwendet wird.Wie verhindert man, dass NSFetchedResultsController die Tabellenansicht aktualisiert, wenn der Controller verschwindet?

Hier ist das Verhalten, das ich erreichen möchte: Nach dem Verschwinden, die UITableView stoppt die Aktualisierung, und wenn der Benutzer zurückkommt, wird die gesamte Tabellenansicht neu geladen. Andernfalls dauert das Einfügen von Ereignissen vom anderen Controller länger, da neue Zeilen in UITableView erstellt werden, auch wenn sie nicht sichtbar sind.

Ich frage mich, wie ich dieses Verhalten erreicht werden kann, da es nicht, wie ich es sein würde erwarten, scheint zu funktionieren:

ich in viewWillDisappear den Delegierten des NSFetchedResultsController auf Null gesetzt haben, und es wiederherstellen in viewWillAppear, zusammen mit einem Anruf zu [UITableView reloadData];

Irgendwie kann ich die neuen Daten nicht sehen und vermute, dass dies auf die Art und Weise zurückzuführen ist, wie NSFetchedResultsController aufhört, abzurufen, wenn es keinen Delegaten hat.

Wie kann ich Updates zu UITableView ordnungsgemäß "suspendieren", wenn es verschwindet, aber immer noch in der Lage, den gesamten Datensatz zu sehen, wenn der Controller wieder erscheint?

Antwort

7

Einstellung Versuchen performFetch: zum NSFetchedResultsController in viewWillAppear: sendet, nachdem Sie seinen Delegaten zurück zu self gesetzt haben.

1

Anstatt die delegate des NSFetchedResultsController auf Null in viewWillDisappear Einstellung versuchen, ein Objekt von NSFetchedResultsController zu null

+0

Es wäre gut zu wissen, warum downvote? – user427969

2

Ich denke, Sie müssen die Tabellenansicht Updates nicht "suspendieren". Ein UITableView wird sowieso nur Daten von NSFetchedResultsController für sichtbare Zellen anfordern. Wenn die Tabellenansicht nicht sichtbar ist, werden keine Aktualisierungen ausgelöst.

Haben Sie getestet, ob das Einfügen von Ereignissen von einem anderen Controller wirklich länger dauert? Ich bezweifle das. Was sagt Instruments?

Wenn Ihre Delegatmethoden ausgelöst werden, können Sie immer noch überprüfen, ob die Tabellenansicht sichtbar ist, bevor Sie Aktualisierungen vornehmen.

Danach tun Sie genau wie von rob vorgeschlagen: tun Sie eine performFetch: in viewWillAppear:.

+1

Auch wenn es keine echten UI-Aktualisierungen gibt, "initiate" 'beginUpdates' bei' controllerWillChangeContent' und 'endUpdates' bei' controllerDidChangeContent' den FRC-Thread für einige Zeit. –

0

Was ist mit diesem rohen Ansatz? Nicht getestet.

@property (nonatomic) BOOL bruteForceReload; 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    self.bruteForceReload = NO; 
} 

-(void)viewDidDisappear:(BOOL)animated { 
    [super viewDidDisappear:animated]; 
    self.bruteForceReload = YES; 
} 

-(void)setBruteForceReload:(BOOL)bruteForceReload { 
    _bruteForceReload = bruteForceReload; 
    if (_bruteForceReload) { 
     [self.tableView reloadData]; 
    } 
} 

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

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
      atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type 
{ 
    if (!self.bruteForceReload) { 
     switch(type) { 
      case NSFetchedResultsChangeInsert: 
       [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
       break; 

      case NSFetchedResultsChangeDelete: 
       [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
       break; 

      default: 
       return; 
     } 
    } 
} 

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject 
     atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type 
     newIndexPath:(NSIndexPath *)newIndexPath 
{ 
    if (!self.bruteForceReload) { 
     UITableView *tableView = self.tableView; 

     switch(type) { 
      case NSFetchedResultsChangeInsert: 
       [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
       break; 

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

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

      case NSFetchedResultsChangeMove: 
       [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
       [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
       break; 
     } 
    } 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
    if (!self.bruteForceReload) { 
     [self.tableView endUpdates]; 
    } else { 
     [self.tableView reloadData]; 
    } 
} 
Verwandte Themen