6

Ho migliaia di punti nel mio database Core Data e mi piacerebbe averli tutti nella mia tabellaView ma non voglio recuperarli in memoria tutti in una volta, ma io vorrebbe usare NSFetchedResultsController e metterli in batch con una certa costante. L'ho impostato come ho visto in molte esercitazioni e ho impostato la proprietà fetchBatchSize ma ci sono voluti diversi secondi per caricare il controller di visualizzazione prima che venisse mostrato.Dati principali NSFetchedResultsController e dimensione batch impostata carica tutte le righe

Questa funzione è chiamata in viewDidLoad:

- (void)initPositionsFetch { 
    // Initialize Fetch Request 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"OpenPositionCD"]; 

    // Add Sort Descriptors 
    [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:NO]]]; 

    // Add predicate 
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"moduleId == %@", _module.moduleId]]; 

    [fetchRequest setFetchBatchSize:100]; 

    [fetchRequest setIncludesPendingChanges:NO]; 

    // Initialize Fetched Results Controller 
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:temporaryContext sectionNameKeyPath:nil cacheName:nil]; 

    // Configure Fetched Results Controller 
    [self.fetchedResultsController setDelegate:self]; 

    // Perform Fetch 
    NSError *error = nil; 
    [self.fetchedResultsController performFetch:&error]; 

    if (error) { 
     NSLog(@"Unable to perform fetch."); 
     NSLog(@"%@, %@", error, error.localizedDescription); 
    } 
} 

metodi NSFetchedResultsControllerDelegate:

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

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

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 
    switch (type) { 
     case NSFetchedResultsChangeInsert: { 
      [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
     } 
     case NSFetchedResultsChangeDelete: { 
      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
     } 
     case NSFetchedResultsChangeUpdate: { 
      [self configureCell:(PanelPositionCell *)[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
      break; 
     } 
     case NSFetchedResultsChangeMove: { 
      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
     } 
    } 
} 

UITableView metodi delegato:

#pragma mark - UITableViewDataSource 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    if (_tracksVisible) 
     return 1; 
    else 
     return [[self.fetchedResultsController sections] count]; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if (_tracksVisible) 
     return [_tracks count]; 
    else { 
     NSArray *sections = [self.fetchedResultsController sections]; 
     id<NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:section]; 

     return [sectionInfo numberOfObjects]; 
    } 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier; 
    if(_tracksVisible) 
     CellIdentifier = TrackCellIdentifier; 
    else 
     CellIdentifier = PositionCellIdentifier; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

    if(_tracksVisible) { 
     [((PanelTrackCell *)cell) setValuesByTrackCD:[_tracks objectAtIndex:indexPath.row]]; 
    } else { 
     [self configureCell:(PanelPositionCell *)cell atIndexPath:indexPath]; 
    } 

    return cell; 
} 

- (void)configureCell:(PanelPositionCell *)cell atIndexPath:(NSIndexPath *)indexPath { 
    // Fetch Record 
    NSManagedObject *record = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    OpenPositionCD *position = (OpenPositionCD *)record; 

    // Update Cell 
    [cell setValuesByOpenPositionCD:position]; 
} 

Qual è problema con questo? Perché sta caricando tutte le righe? Potrebbe esserci un problema con il modello di Core Data? Ho provato a rimuovere il predicato e non aiuta. SortDescriptor deve essere impostato ma è l'unica cosa che mi viene in mente dove potrebbe essere un problema. Voglio che i risultati siano ordinati per data e ora. Timestamp è la proprietà Date ed è impostato per essere indicizzato. In che modo i risultati possono essere dosati quando devo prima averlo ottenuto e quindi posso ordinarli in base al tempo? Non dovrebbe essere un problema che sto usando tableView per mostrare un altro dato tramite switch (_tracksVisible), giusto?

Ho anche cercato di recuperare i risultati in fondo con questo codice:

[[[self fetchedResultsController] managedObjectContext] performBlock:^{ 
     NSError *error = nil; 
    [self.fetchedResultsController performFetch:&error]; 

    if (error) { 
     NSLog(@"Unable to perform fetch."); 
     NSLog(@"%@, %@", error, error.localizedDescription); 
    } 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      [_tableView reloadData]; 
     }]; 
}]; 

Era successo che di controllo è stato mostrato molto prima, ma poi UI congelamento e ci vuole quasi lo stesso tempo di prima.

risposta

0

Prova con valore più basso BatchSize, forse 20

[fetchRequest setFetchBatchSize: 20];

Inoltre si può provare aggiungere initPositionFetch

[fetchRequest setFetchLimit: 20];

0

Sembra che tu stia utilizzando un contesto che ha un altro contesto tra questo e il coordinatore di negozio persistente. Ho trovato questo post durante la ricerca dello stesso problema: le mie dimensioni batch sono ignorate dalla mia richiesta di recupero perché sto usando un contesto nidificato. Cerca qui maggiori informazioni e segui i link al post SO correlato e apri la segnalazione bug radar: https://github.com/Simperium/simperium-ios/issues/425. Questo è piuttosto schifoso che Core Data è stato intorno così a lungo e qualcosa apparentemente comune come questo è ancora un problema. Ad ogni modo, potrebbe essere utile depositare un radar su di esso. Anche se lo chiudono come duplicato, forse vedranno che è un problema che molte persone stanno avendo.

Problemi correlati