NSFetchedResultsController `performFetch:` 结果不再排序

Posted

技术标签:

【中文标题】NSFetchedResultsController `performFetch:` 结果不再排序【英文标题】:NSFetchedResultsController `performFetch:` Results No Longer Sorted 【发布时间】:2011-09-17 01:37:46 【问题描述】:

我用 NSFetchedResultsController 管理了一个 tableview,它的获取请求对日期属性使用简单的排序。它在第一次加载时正确排序,但是当我刷新或调用 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];
    );

【问题讨论】:

这个排序描述符在哪里不起作用? 我们需要带有实际NSSortDescriptor 的代码。上面的代码中没有这样的东西。 哦,对不起,我贴出来了…… 你在哪里调用getFetchedResultsControllerloadMore中的方法? 是综合属性,我只是重写get方法 【参考方案1】:

首先,您尝试在另一个毫无意义的队列上运行获取结果控制器 (FRC)。不要混淆从网络下载数据和从本地持久存储文件获取数据。

网络操作可以在后台执行,但 FRC 等 UI 相关操作需要在前台执行。如果您在另一个队列中修改 FRC,它将与 tableview 不同步。

其次,您必须删除 FRC 的缓存并调用它的performFetch您对获取请求进行任何更改。在某些情况下,您随后会更改 fetchLimit。这可能会产生不可预测的行为(尽管在这种情况下,更改似乎毫无意义,因为它从未被使用过。)

我建议从队列中删除 FRC 代码,而只需让它以标准方式响应在另一个队列上所做的更改。然后我会清理对获取请求的更改。最后,我将摆脱获取限制。当你有排序时,它们很少能提高效率,甚至更少。

【讨论】:

删除调度块还是...?【参考方案2】:

似乎解决了。当应用程序之前进入后台时,我将数据保存到核心数据。现在我从互联网下载数据后保存它。

【讨论】:

以上是关于NSFetchedResultsController `performFetch:` 结果不再排序的主要内容,如果未能解决你的问题,请参考以下文章

在 Core Data 应用程序中调用 performFetch 后,是不是需要手动更新表视图?