iOS using UITableView reloadData vs endUpdates - ios

I am writing an app with a basic UITableView that shows NSManagedObjects that are loaded from CoreData.
There is also a background process that is running and notifies the viewController using NSNotificationCenter of any changes to the CoreData NSManagedObject (IE: Using NSInserted/Updated/DeletedObjectsKey). I have a few questions regarding the best way to update the tableView after the view receives the notification of changed data.
Is it better to call reloadData on the tableView or figure out a diff on the data and do the inserts/deletes/updates inside a tableview.BeginUpdates() - tableView endUpdates()?
Is it a valid practice to refresh the tableView while a user is interacting with the tableView?
Is there an easy way that I am missing to do a diff between two arrays of the CoreData NSManagedObjects and apply to the tableView?
I hope I am not overcomplicating things

It depends. If you want just refresh data without any animation then use reloadData. In the case when you build up an user-friendly smooth data changing animations, it would be better to calculate the diff and insert/delete rows with some beautiful animation
User is not interacting with tableView infinitely. You may track when table is not dragging and update the data, but refreshing view to show actual data is common practice today. For example, at the web it is AJAX technology. Also, as I mentioned in 1, use animation to attract user's attention to new data
As it mentioned in the comments, in your case using NSFetchedResultsController would be better

Related

Best performance to passing data between controllers

I’am studying RxSwift and have this one case.
From tableView cell, I go to info restaurant, and if I change the rate for this restaurant, I want to change this rate in tableView too, but I don’t want to update tableView, because restaurants are downloaded from the backend, cause restaurants data is not loaded every time when viewWillApear is called. Now I’m using cloujers, in prepareForSegue, I’m setting a new rate in cell from its info. I read that the cloujers are used in a lot of resources, can this be done with the help of RxSwift or another best way?
This is best library to work with collection view and table view in RxSwift
https://github.com/RxSwiftCommunity/RxDataSources

Do you put NSFetchRequest into cellForRowAtIndexPath?

It seems me somewhat slow to perform NSFetchRequest in cellforRowAtIndexPath.
How do you treat it? Is it more memory / time efficient to perform it in viewDidLoad, cache result into a dictionary, and use that in cellForRowAtIndexPath?
It is a bad idea due to performance reasons, as #Paulw11 mentioned in his comment. Additionaly, you will execute fetch requests more times than it's actually needed (while scrolling the table view back and forth), because cellForRowAtIndexPath is called each time a cell is reused.
I would recommend using NSFetchedResultsController. It is designed specifically to show Core Data records in UITableView. It allows batch fetching (doesn't fetch all the objects, but only the ones that need to be displayed). Also you will be able to easily track changes in your model.

UITableView - Delayed update when using sections

I've been searching for a few days, and have continued to learn from reading the apple docs and various tutorials, but there's a problem which I can't seem to get a handle on.
I have a simple app that keeps track of projects, with a single Core Data Entity (ProjectEntry). All the attributes are strings at the moment. It's basically a combination of Paul Hegarty's Core Data lectures and Tim Roadley's web tutorial.
I can add and save Entities and populate a tableview with the data. For the moment, I'm using the CoreDataTableViewController subclass that Hegarty provides in the lecture. I'm mentioning that because...
When my UITableView isn't divided into sections, the new information "instantly" appears in the UI after adding a new entry. However, when I add sections ( via sectionNameKeyPath), the new data still saves, but shows up only after refreshing several times OR waiting 30 seconds before refreshing(via a pull-to-refresh mechanism, which Hegarty also provided).
The tableview delegate methods all seem to be working, as do the NSFetchedResultsController's methods. Using the Stanford/Hegarty CoreDataTableViewController subclass in the past has yielded success, and I've learned a lot reading through the implementation file itself.
The controllers are embedded in a Navigation controller, with the managed object context being passed among the controllers via the prepareForSegue method. Some simple logging shows me the managed object context, initially obtained via a UIManagedDocument, is being successfully passed along.
I've tried the [self.tableview reloadData] and/or the beginUpdates/endUpdates in viewWillAppear, but the delay persists.
What is it about dividing the tableview into sections that's causing the delay? Would calling reloadSections on the tableview be necessary? Like I said, the entries are saved with Core Data and the fetchedResultsController populates the non-sectioned tableview instantly...
It's probably something obvious that I'm just missing, but any help would be appreciated.
Warren Burton's comment above made me re-check if my managed object context behavior was consistent while being passed among the view controllers via the prepareForSegue method.
So, as mentioned in my last comment above, it seems to solve the problem for the moment:
from above:
The initial view controller is non-tableview, which can segue to a UIViewController to add a ProjectEntry, or segue to a UITableViewController which lists saved project entries. This initial view controller creates or uses the UIManagedDocument. By setting a one-line check to see if the UIManagedDoc is being used in this initial view controller's viewWillAppear method, the "delay" in displaying new section data in the tableview seems to stop. I'll test it some more before saying the issue is solved. This way, the shared managed object contexts seem better "bound together" via the managed doc - vapul

Moving from a simple TableViewController based App to a Grid View (Similar to Flipboard) while maintaining CoreData and NSFetchedResultsController

I am hard at work at my first app which is based around a simple TableViewController concept. It's using CoreData in the background, so when I press the ADD button, it brings up a ModalVC, the user adds in data, it gets added to the Entities and Attributes and that's then displayed in the TableViewCOntroller using the NSFetchedResultsController.
While that is sufficient for a template, I'm not happy with that UI for an actual release and what I want is someething closer to Flipboard, or the new iOS 7 only Cook App (iPad Only) with the Grids and that style of approach.
My question is, if I get the UI designed appropriately, can I use the grid approach in my app to replace the TableViewController, while maintaining my backend structure for CoreData and the efficiency of NSFetchedReusltsController. If so, any advice into how I approach this would be very much appreciated!
Take a look at UICollectionView. In general it works nicely with an NSFetchedResultsController. Beware however, that when starting out, just use the NSFetchedResultsDelegate method
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
Implementing the other method required some extra work as compared to a tableView, but I guess you first want it to just work with UICollectionView, so just use the 'hammer:
-reloadData
on the collectionView in the FRCDelegate.

Writing to coredata when device is put to sleep?

I have abit of a problem, I have a coredata object that is used to populate a UITableView. Each UITableViewCell has a couple of buttons that I am using as check boxes, when the user presses one of these text boxes I would like to update coredata and reload the UITableView so all of the arrays I have are updated to reflect the new data.
Thinking about this I have come to the conclusion that its abit redundant or overkill to be reloading the UITableView every time a button is pressed because some of these UITableViews will contain hundreds of rows with two editable UIButtons each.
So I thought that maybe I should update the current array instead then when the view is either exited or the device is put to sleep I could update the coredata object then? the only thing being I don't really know if this is the right thing to do or possible.
The reason this is such a problem is that when I change a button from say a tick to a cross if I scroll away then come back the buttons tick or cross s reverted to its old value.
I would like to know the best way to handle this case as I have never done anything like this before.
You should use an NSFetchedResultsController and its delegate methods to populate the UITableView. Then when the user taps a button, you simply update the corresponding Core Data entity and not the cell. The NSFetchedResultsController will then call its delegate methods, and you can update just that one cell on which the user made a change.
Also, in cellForRowAtIndexPath, you simple fid the corresponding CoreData entity, and use its attributes/properties to adjust the display of the cell.
Remember, that you must always use some data (NSArray usually) from which to read what to do for the cell at the indexPath when the tableView calls cellForRowAtIndexPath:.
This way, when the fetchedResutsController call its delegate methods, you can simply call reloadCellAtIndexPath on the tableView and then the tableView will call cellForRowAtIndexPath again. As the Core Data entity has been updated, your logic for adjusting the display for that cell will cause the cell to look as it should. It's important that you only ever adjust the way a cell looks in cellForRowAtIndexPath, and base the look on a CoreData entity. Change the look of a cell in multiple places, and you will get problems.

Resources