6

Mam tysiące punktów w mojej bazie danych podstawowych i chciałbym mieć je wszystkie w moim tableView, ale nie chcę ich pobrać do pamięci za jednym razem, ale chciałbym użyć NSFetchedResultsController i wsypać je z pewną stałą. Ustawiłem to tak, jak widziałem w wielu samouczkach i ustawiłem właściwość fetchBatchSize, ale ładowanie kontrolera podglądu zajęło kilka sekund, zanim zostanie pokazane.Core Data NSFetchedResultsController i zestaw wielkości wsadowych ładuje wszystkie wiersze

Ta funkcja jest wywoływana w 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); 
    } 
} 

NSFetchedResultsControllerDelegate metody:

#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 metod Delegat:

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

Co to jest problem z tym? Dlaczego ładuje wszystkie wiersze? Czy może być problem z modelem Core Data? Próbowałem usunąć predykat i to nie pomaga. SortDescriptor musi być ustawiony, ale to tylko coś, co przyszło mi do głowy, gdzie może być problem. Chcę, aby wynik był sortowany według znacznika czasu. Znacznik czasu ma właściwość Date i jest ustawiony na indeksowanie. W jaki sposób wyniki mogą być grupowane, gdy najpierw muszę je zdobyć, a następnie mogę je sortować według czasu? Nie powinno być problemu, że używam tableView do pokazywania innych danych przez przełącznik (_tracksVisible), prawda?

Próbowałem nawet przynieść efekty w tle z tym kodem:

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

Co się stało, że sterownik został pokazany dużo wcześniej, ale to Ui zamrożenie i zajmuje prawie taki sam czas jak poprzednio.

Odpowiedz

0

Spróbuj z niską wartością BatchSize, może 20

[fetchRequest setFetchBatchSize 20];

Ponadto można spróbować dodać initPositionFetch

[fetchRequest setFetchLimit: 20];

0

Wygląda na to, że możesz użyć kontekstu, który ma inny kontekst między nim a stałym koordynatorem sklepu. Znalazłem ten wpis podczas wyszukiwania tego samego problemu: moje rozmiary partii są ignorowane przez moją prośbę o pobranie, ponieważ używam zagnieżdżonego kontekstu. Tutaj znajdziesz więcej informacji i linki do powiązanego zgłoszenia SO i otwartego raportu o błędzie: https://github.com/Simperium/simperium-ios/issues/425. Jest to dość brzydkie, że Core Data jest w pobliżu tej długiej i pozornie powszechnej, ponieważ jest to nadal problem. W każdym razie dobrze byłoby złożyć na nim radar. Nawet jeśli zamkną to jako duplikat, być może zobaczą, że jest to problem, który wielu ludzi ma.

Powiązane problemy