Ensembles 2 with NSFetchedResultsControllerDelegate tableView update methods causing crash - ios

Using NSFetchedResultsController delegate method controller
(_:didChange: at:for:newIndexPath:), between tableView.beginUpdates() in controllerWillChangeContent(_:) and tableView.endUpdates() in controllerDidChangeContent(_:), results in objects with nil properties (including the uniqueIdentifier, which is normally set in awakeFromInsert()) being created when merging changes from different devices, and related crash. The problem doesn't occur when only the controllerDidChangeContent(_:) delegate method with tableView.reloadData() is implemented instead.
Any advice on how to eliminate this problem would be appreciated.

Adding tableView.reloadData() in controllerWillChangeContent(_:) just before beginUpdates() seems to solve the problem. It ensures that data in the tableView is in sync with that in the fetchedResultsController (FRC) before the tableView is modified by the FRC delegate methods.

Related

Additional section in UITableView with NSFetchedResultsController

I am currently implementing a UITableViewController with an NSFetchedResultsController. It fetches some objects from CoreData and displays them as rows in one section as expected.
Now, I would like to have one additional section with exactly one row that displays aggregated information about the fetched objects.
From what I know, one NSFetchedResultsController can only have one fetch request, but I would have to use another one to get the aggregated information.
Perhaps I should use one NSFetchedResultsController for the Overall section and another one for the single object section, but this feels kind of strange to me.
What do you think?
You may consider to use one fetchedResultController. And add some observer functions in the delegate of fetchedResultController:
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{
[self updateAggregatedInformation : basedOnFecthedObjects]; //with collection keypath methods;
[self updateTableView];
}
There is a little overhead in the tableView DataSource, but gain in performance.
I just solved the problem and it was more easy than I thought.
The NSFetchedResultsControllerDelegate receives messages from the FRC and so the delivered IndexPath.section attributes have be adapted according to the tableView. The same needs to be done the other way around when the tableView calls the FRC to create cells that are backed up by the fetched entities.

iOS/Swift - UITableView reloadData not being called

I have the following method on my table view controller class:
func reloadInputFields() {
dispatch_async(dispatch_get_main_queue()) {
self.tableView.beginUpdates()
self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: .Automatic)
self.tableView.endUpdates()
}
}
This is called from an NSNotification. The runtime enters this method fine and appears to call reloadSections. However it never actually does. Obviously I am executing on the main thread here as it is a UI update but I have also tried on a background thread. I have also tried just calling tableView.reloadData() instead of reloadSections but no joy there. The table view definitely exists and I have checked that the pointer is correct.
Breakpoints in cellForRowAtIndexPath numberOfSectionsInTableView heightForRowAtIndexPath numberOfRowsInSection etc are not being hit and the table is not reloading.
My delegate and dataSource are set correctly as verified here:
I've been struggling with this for several hours now and it's totally bested me. Any suggestions would be gratefully received.
Some suggestions to solve this issue:
1. Make sure you have IBOutlet connection to the UITableView.
2. Check delegate and datasource. If necessary, write them programmatically.
3. Make sure your tableView is populated with data before triggering notification.
4. Avoid beginUpdates and endUpdates and use only reloadData on main thread.
Is the table view active when the notification is fired?
Check if the table view controller is released (It is not active. Probably not shown on the screen)

Using reloadRowsAtIndexPaths when the update of a NSFetchedResultsController is triggered

I have some rows of my UITableView that get updated and then trigger the method controller:didChangeObject:atIndexPath:forChangeType:newIndexPath of the NSFetchedResultsControllerDelegate delegate.
I usually update the rows in the tableView using reloadRowsAtIndexPaths with an animation, but it happens that sometimes the method is triggered because of a change that is not visible and is that case, I don't want to reload the row with an animation.
The method doesn't give the previous state of the object. Is there a way to do it (I didn't find any method of the delegate that might do)?
If your delegate is also your TableViewController, you could just check your UITableView's data source at the IndexPath. The reloadRowsAtIndexPaths method knows the index.

Safequarding against crashes while swapping out NSFetchedResultsController for UITableView

I'm trying to swap the NSFetchedResultsController used for a UITableView, but it takes a few lines of code and I'm worried that another thread could try to access it halfway through and cause the app to crash. Here's the code I'm currently using:
The fetched results controller is created in the getter if it does not already exist, so the next time the table view tries to access it, it will be regenerated.
- (void)regenerateFetchedResultsController
{
self.fetchedResultsController = nil;
[self loadData]; // Loads data into the fetched results controller.
[self.tableView reloadData];
}
I'd guess that if something tried to access the FOC in the middle of this method things would go wrong, so I thought I would use UITableView's beginUpdates and endUpdates methods and the start and end of the method.
However, it seems you can't have reloadData between beginUpdates and endUpdates, so I don't really know what else to try.
All table view data source methods (numberOfSectionsInTableView, numberOfRowsInSection, cellForRowAtIndexPath, ...) are only called on the main thread. Therefore, if you run your regenerateFetchedResultsController also on the main thread, it will not happen that any other method accesses the FRC in that time.
It may depend on what [self loadData] exactly does, but setting the fetched results controller to nil and letting it "auto-recreate" by calling reloadData is a standard pattern.

help core data tableview not reloading

i am using core data...my table view does not reload say if i add a new row to the table. until i terminate the app and re open it...im calling reloadData in my root controller viewwillappear method... any help would be appreciated
thanks in advance
I am guessing you are using a NSFetchedResultsController? If you are not then you need to be with a UITableView. Once you do, make sure you have your UITableViewDatasource configured as the delegate to the NSFetchedResultsController. Once you do that, you will not need to call -reloadData at all because the NSFetchedResultsController will monitor changes in the NSManagedObjectContext and update the UITableViewDatasource as needed via the delegate methods.

Resources