When the app opens changes to the UITableView flash by really fast

68 Views Asked by At

I have a UITableView which gets its data from a Core Data stack. Functionally this works as expected.

What I however have noticed is that sometimes when you start the app you see past changes (made i.e. on a different device) flash by. The also happens when the app is installed on an new device and the iCloud-Data is not fully loaded. Depending on the amount of changes it can take a second or two for all the table cells to be added, changed, deleted again. If the user is patient then all is good and the correct data is displayed after a few seconds. If the user however interacts with the data, which ist just flashing by because it is being updated it can obiously cause the app to crash.

How can I prevent the, what I can only assume is merge data from displaying directly to the UITableView? Here are the probably relevant parts of my code.

- (void)viewDidLoad {

    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(persistentStoreDidImportUbiquitousContentChanges:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:[[MyDataModel sharedDataModel] persistentStoreCoordinator]];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(persistentStoreDidChange:) name:NSPersistentStoreCoordinatorStoresDidChangeNotification object:[[MyDataModel sharedDataModel] persistentStoreCoordinator]];
... 
}


- (void)persistentStoreDidImportUbiquitousContentChanges:(NSNotification *)notification {

    dispatch_async(dispatch_get_main_queue(), ^{
        NSManagedObjectContext *mainContext = [[MyDataModel sharedDataModel] mainContext];
        [mainContext mergeChangesFromContextDidSaveNotification:notification];

        [self reloadTableData];
    });

}

- (void)persistentStoreDidChange:(NSNotification *)notification {

    [self reloadTableData];

}

- (void)loadLists {

    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[List entityName]];
    [fetchRequest setPropertiesToFetch:@[@"name"]];
    [fetchRequest setFetchBatchSize:40];

    NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    [fetchRequest setSortDescriptors:@[sortByName]];


    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:[[MyDataModel sharedDataModel] mainContext]
                                                                      sectionNameKeyPath:nil
                                                                               cacheName:nil];
    _fetchedResultsController.delegate = self;

    NSError *fetchRequestError = nil;
    if (![_fetchedResultsController performFetch:&fetchRequestError]) {
        NSLog(@"Error while fetching lists: %@ %@", fetchRequestError.localizedDescription, fetchRequestError.localizedFailureReason);
    }
    ...
}

- (void)reloadTableData {

    [self loadLists];
    [_tableView reloadData];

}

Thanks in advance

1

There are 1 best solutions below

2
On

You could set the delegate of your fetched results controller to nil, inform the user that the UI is temporarily unavailable because it still needs to receive updates, and then (after sufficient time has elapsed to receive all the Core Data changes) switch the delegate back to self, update the table and unlock the UI.