Search code examples
iosobjective-cuitableviewcore-datansfetchedresultscontroller

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


My tableview isnt being populated by data being pulled in nsfetchedresultscontroller until the app is restarted or i go to another view controller and back. I've never had this problem before, very weird.

Code:

- (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 pulls in all the posts for the tableview and saves them to 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];

    }];
}

The getPostsFeedWithCompletion method:

-(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");
                                    }
                                }];
}

heres the nsfetchedresultscontroller instantiation

- (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;

}

Heres is the log from the MagicalRecord Save:

[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 ***

Solution

  • Turns out it was a problem with my predicate.
    NSArray *following was being hard set in the getter for the FRC but its empty until the getPosts api call completes.