带有 fetchedResultsController 的 Tableview 在应用重启或视图重新加载之前不会更新新内容

Tableview with fetchedResultsController not updating new content until app restart or view gets reloaded

我的表视图不会被 nsfetchedresultscontroller 中拉取的数据填充,直到应用程序重新启动或我转到另一个视图控制器并返回。我以前从来没有遇到过这个问题,很奇怪。

代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 60, 0);

    [super viewDidLoad];


    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }


    UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
    [refresh addTarget:self
                action:@selector(refresh)
      forControlEvents:UIControlEventValueChanged];
    self.refreshControl = refresh;

    UITableViewController *tableVC = [[UITableViewController alloc]initWithStyle:UITableViewStylePlain];
    [tableVC setTableView:self.tableView];
    tableVC.refreshControl = self.refreshControl;

    [self.tableView setContentOffset:CGPointMake(0.0f, -60.0f)
                                          animated:YES];
    [self getPosts];


    // Do any additional setup after loading the view.
}

getPosts 获取 tableview 的所有帖子并将它们保存到 coredata。

-(void)getPosts
{
    [self.refreshControl beginRefreshing];
    [self.postsController getPostsFeedWithCompletion:^(BOOL complete, NSArray *posts) {
        [self.refreshControl endRefreshing];
    } failure:^(NSString *message) {
        [self.refreshControl endRefreshing];
        ALAlertBanner *alert = [ALAlertBanner alertBannerForView:self.view
                                                           style:ALAlertBannerStyleFailure
                                                        position:ALAlertBannerPositionTop
                                                           title:@"Error"
                                                        subtitle:@"Error retrieving posts, please try again."];
        [alert show];

    }];
}

getPostsFeedWithCompletion 方法:

-(void)getPostsFeedWithCompletion:(void (^)(BOOL complete, NSArray *posts))complete
                          failure:(void (^)(NSString *message))failure

{
    [[APIManager sharedManager] getPath:@"posts/feed"
                             parameters:nil
                                success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                    DLog(@"response: %@", responseObject);

                                    NSArray __block *posts;

                                    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
                                        posts = [self createPosts:responseObject[@"posts"] inContext:localContext];
                                    } completion:^(BOOL success, NSError *error) {
                                        if(complete){
                                            complete(YES, posts);
                                        }
                                    }];

                                }
                                failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                    DLog(@"error: %@", error);
                                    if(failure){
                                        failure(@"Error retrieving posts");
                                    }
                                }];
}

这里是 nsfetchedresultscontroller 实例化

- (NSFetchedResultsController *)fetchedResultsController {

    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"Post" inManagedObjectContext:context];
    [fetchRequest setEntity:entity];

    NSArray  *following = [[SessionManager getInstance].currentLoggedInUser.follows allObjects];

    NSMutableArray *predicateArray = [NSMutableArray array];
    NSDate *now = [NSDate date];

    [predicateArray addObject:[NSPredicate predicateWithFormat:@"account IN %@", following]];
    [predicateArray addObject:[NSPredicate predicateWithFormat:@"expiration > %@", now]];

    NSCompoundPredicate *filterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateArray];
    [fetchRequest setPredicate:filterPredicate];
    [fetchRequest setFetchBatchSize:20];


    NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                              initWithKey:@"expiration" ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                        managedObjectContext:context
                                          sectionNameKeyPath:nil
                                                   cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;

}

这是来自 MagicalRecord 保存的日志:

[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Saving <NSManagedObjectContext (0x7ffcea601bd0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffcea601bd0) Context UNNAMED is about to save. Obtaining permanent IDs for new 22 inserted objects
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Saving <NSManagedObjectContext (0x7ffceba008f0): *** DEFAULT ***> on *** BACKGROUND THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffceba008f0) Context DEFAULT is about to save. Obtaining permanent IDs for new 22 inserted objects
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Saving <NSManagedObjectContext (0x7ffcea746c10): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffcea746c10) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 22 inserted objects
_70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7ffcea746c10) → Finished saving: <NSManagedObjectContext (0x7ffcea746c10): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***

原来是我的谓词有问题。
NSArray *following 在 FRC 的 getter 中被硬设置,但在 getPosts api 调用完成之前它是空的。