NSFetchedResultsController `executeFetch:` результаты больше не сортируются - PullRequest
1 голос
/ 17 сентября 2011

Я управлял просмотром таблицы с помощью NSFetchedResultsController, запрос выборки которого использует простую сортировку по атрибуту даты.Он сортируется правильно при первой загрузке, но когда я обновляю или вызываю метод loadMore (см. Ниже), порядок сортировки выглядит случайным.

Метод NSFetchedResultsController

- (NSFetchedResultsController *)getFetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }
    [NSFetchedResultsController deleteCacheWithName:@"LatestNews"];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:@"News" inManagedObjectContext:self.managedObjectContext]];
    [request setFetchLimit:kDefaultNewsLimit];
    [request setFetchBatchSize:20];
    [request setIncludesPropertyValues:NO];
    NSSortDescriptor *dateSortor = [NSSortDescriptor sortDescriptorWithKey:@"dateAdded" ascending:NO];
    [request setSortDescriptors:[NSArray arrayWithObject:dateSortor]];

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"LatestNews"];
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

Метод loadMore

- (void)loadMore {
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    UIActivityIndicatorView *loadingIndicator = (UIActivityIndicatorView *)[loadMoreButton viewWithTag:3];
    [loadingIndicator startAnimating];
    NSUInteger newsLoaded = self.numberOfLimitedNews;

    double delayInSeconds = 1.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        //fetch news from internet with date args
        NSDate *lastNewsDate;
        NSDate *beginTime, *endTime;
        NSDictionary *condition;


        [self.fetchedResultsController.fetchRequest setFetchLimit:self.numberOfLimitedNews+kDefaultNewsLimit];
        [NSFetchedResultsController deleteCacheWithName:@"LatestNews"];
        [self.fetchedResultsController performFetch:nil];
        if (self.numberOfLimitedNews - newsLoaded < kDefaultNewsLimit) {

            News *lastNews = [newsHelper getLastNews:@"LatestNews" idValue:nil];
            lastNewsDate = lastNews.dateAdded;
            beginTime = [NSDate dateWithTimeIntervalSince1970:0];
            if (!lastNewsDate) {
                endTime = [NSDate date];
            }
            else {
                endTime = lastNewsDate;
            }
            condition = [NSDictionary dictionaryWithObjectsAndKeys:beginTime, @"beginTime", endTime, @"endTime", nil];
            NSUInteger newsToFetch = kDefaultNewsLimit - self.numberOfLimitedNews % kDefaultNewsLimit;

            [newsHelper getNumberOfNews:newsToFetch forLanguages:@"en" withCondition:condition];
            [self.fetchedResultsController.fetchRequest setFetchLimit:self.fetchedResultsController.fetchRequest.fetchLimit+newsToFetch];
        }

        [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
    });
}

Результаты:

2011-09-13 16:48:20.959 HJNews[5971:bc03] 2011-02-04 06:00:00 +0000
2011-09-13 16:48:21.079 HJNews[5971:bc03] 2011-09-13 08:29:48 +0000
2011-09-13 16:48:21.230 HJNews[5971:bc03] 2011-02-19 01:30:00 +0000
2011-09-13 16:48:21.463 HJNews[5971:bc03] 2011-09-13 08:45:00 +0000
2011-09-13 16:48:21.879 HJNews[5971:bc03] 2011-03-06 02:00:00 +0000
2011-09-13 16:48:22.143 HJNews[5971:bc03] 2010-12-01 02:40:00 +0000
2011-09-13 16:48:22.229 HJNews[5971:bc03] 2011-09-13 02:03:43 +0000
2011-09-13 16:48:22.313 HJNews[5971:bc03] 2011-09-13 08:10:33 +0000
2011-09-13 16:48:22.446 HJNews[5971:bc03] 2011-01-02 06:00:00 +0000
2011-09-13 16:48:22.627 HJNews[5971:bc03] 2011-09-13 08:45:00 +0000
2011-09-13 16:48:22.978 HJNews[5971:bc03] 2011-01-23 02:00:01 +0000
2011-09-13 16:48:23.092 HJNews[5971:bc03] 2011-09-13 03:35:40 +0000
2011-09-13 16:48:23.196 HJNews[5971:bc03] 2011-02-18 06:20:00 +0000
2011-09-13 16:48:23.346 HJNews[5971:bc03] 2011-09-13 00:00:00 +0000
2011-09-13 16:48:23.812 HJNews[5971:bc03] 2011-02-08 06:00:00 +0000
2011-09-13 16:48:23.980 HJNews[5971:bc03] 2011-09-12 01:40:10 +0000
2011-09-13 16:48:24.179 HJNews[5971:bc03] 2011-01-18 06:00:00 +0000
2011-09-13 16:48:26.257 HJNews[5971:bc03] 2010-12-22 06:30:00 +0000
2011-09-13 16:48:27.783 HJNews[5971:bc03] 2011-02-08 06:00:00 +0000
2011-09-13 16:48:27.784 HJNews[5971:bc03] 2011-09-12 01:40:10 +0000
2011-09-13 16:48:27.785 HJNews[5971:bc03] 2011-01-18 06:00:00 +0000
2011-09-13 16:48:27.785 HJNews[5971:bc03] 2010-12-22 06:30:00 +0000
2011-09-13 16:48:27.786 HJNews[5971:bc03] 2011-09-13 02:10:17 +0000

Метод, вызываемый после извлечения данных из Интернета

- (void)asiRequestFinished:(NSNotification *)notification {
    dispatch_async(dispatch_get_main_queue(), ^{
        [NSFetchedResultsController deleteCacheWithName:@"LatestNews"];
        [self.fetchedResultsController performFetch:nil];
        [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
        UIActivityIndicatorView *loadingIndicator = (UIActivityIndicatorView *)[loadMoreButton viewWithTag:3];
        [loadingIndicator stopAnimating];
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        isRefreshing = NO;
        [refreshView egoRefreshScrollViewDataSourceDidFinishedLoading:self.tableView];
    });
}

Ответы [ 2 ]

4 голосов
/ 18 сентября 2011

Во-первых, вы пытаетесь запустить контроллер результатов выборки (FRC) в другой очереди, которая довольно бессмысленна.Не путайте загрузку данных из сети с извлечением данных из файла локального постоянного хранилища.

Сетевые действия могут выполняться в фоновом режиме, но связанные с пользовательским интерфейсом действия, такие как FRC, должны быть на переднем плане.Если вы измените FRC в другой очереди, он выйдет из синхронизации с представлением таблицы.

Во-вторых, вы должны удалить кэш FRC и вызвать его performFetch после того, как внесет любые изменения в запрос на выборку.В некоторых случаях вы меняете fetchLimit впоследствии.Это может привести к непредсказуемому поведению (хотя в этом случае изменение кажется бессмысленным, поскольку оно никогда не используется.)

Я бы предложил удалить код FRC из очереди и вместо этого просто заставить его реагировать на изменения, сделанные в другой очереди встандартная манераТогда я бы очистил изменения в запросе на выборку.Наконец, я бы избавился от пределов выборки.Они редко улучшают эффективность намного и даже меньше, когда у вас есть сорта.

0 голосов
/ 19 сентября 2011

Кажется, решено. Я сохранил данные в Core Data, когда приложение перешло в фоновый режим. Теперь я сохраняю его после загрузки данных из интернета.

...