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.