Core Data NSFetchedResultsController y el set de tamaños de lote cargan todas las filas

Tengo miles de puntos en mi database de database y me gustaría tenerlos todos en mi tablaView, pero no quiero searchlos en la memory de una vez, pero me gustaría utilizar NSFetchedResultsController y NSFetchedResultsController con algunas constantes. Lo configuré como lo vi en muchos tutoriales y configuré la propiedad fetchBatchSize pero me tomó varios segundos cargar el controller de vista antes de que se muestre.

Esta function se llama en viewDidLoad:

 - (void)initPositionsFetch { // Initialize Fetch Request NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"OpenPositionCD"]; // Add Sort Descriptors [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:NO]]]; // Add pnetworkingicate [fetchRequest setPnetworkingicate:[NSPnetworkingicate pnetworkingicateWithFormat:@"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); } } 

Métodos 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 delegate methods:

 #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]; } 

¿Cuál es el problema con esto? ¿Por qué está cargando todas las filas? ¿Podría ser un problema con el model Core Data? He intentado eliminar el pnetworkingicado y no ayuda. Se debe configurar SortDescriptor, pero lo único que me vino a la mente fue dónde podría ser un problema. Quiero que el resultado sea orderado por timestamp. La timestamp es propiedad de date y está configurada para estar indexada. ¿Cómo se pueden agrupar los resultados cuando primero debo getlos y luego puedo orderarlos por time? No debería ser un problema que estoy usando tableView para mostrar otros datos por el interruptor (_tracksVisible), ¿verdad?

Incluso intenté get resultados en segundo plano con este código:

 [[[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]; }]; }]; 

Lo que sucedió fue que el controller se mostró mucho antes, pero luego se congela la interfaz de usuario y tarda casi el mismo time que antes.

Intente con un valor más bajo en BatchSize, tal vez 20

[fetchRequest setFetchBatchSize: 20];

También puedes probar agregar en initPositionFetch

[fetchRequest setFetchLimit: 20];

Parece que podría estar utilizando un context que tenga otro context entre él y el coordinador de tienda persistente. Encontré esta publicación mientras buscaba el mismo problema: mi request de búsqueda ignora mis tamaños de lote porque utilizo un context nested. Mira aquí para get más información y sigue los enlaces a la publicación SO relacionada y al informe de error de radar abierto: https://github.com/Simperium/simperium-ios/issues/425 . Esto es bastante malo que Core Data haya existido durante tanto time y algo aparentemente común, ya que esto sigue siendo un problema. De todos modos, podría ser bueno archivar un radar en él. Incluso si lo cierran como un duplicado, tal vez vean que es un problema que mucha gente está teniendo.