I can refresh any non-CoreData loaded tableView by calling [nameoftableView reloadData];
But when I call this on my CoreData loaded TVC it does not reload the table. Does this work differently?
It does update it contents if I stop and start the app again - so that it reloads the database, so I know it has the updated content in it.
Cheers Jeff
Without details is difficult to know what is going on, but if you use a simple NSFetchRequest I think you need to execute the query and call reloadData again.
A simple note
I suggest you to use NSFetchedResultsController when dealing with Core Data and UITableViews. raywenderlich has a tutorial on how to use that class in Core Data.
First of all it allows you to deal with a lot of data displayed in a UITableView. In particular, if for the NSFetchRequest you use with, you set a batch size, data will be retrieved in "batches". For example, the first 10. Then if you scroll the other 10 and so on...
In addition you can deal with data changes (update, insertion or deletion) for free using NSFetchedResultsControllerDelegate class (Reference NSFetchedResultsControllerDelegate).
Hope it helps.
Related
I have a bunch of information from a few views (stored in a singleton) that I collected from the user, now all displayed in one confirmation view. How do I take this information and create a new UITableViewCell that one can click on to see the entered information.
And, although this comes later, how do I make sure this data is stored between sessions and never deleted unless done so by the user.
Thanks for the help.
Showing the data in a UITableView is quite trivial, and I suggest you check out the UITableView Class Reference, UITableViewDelegate and UITableViewDataSource protocols to find out how you can do that.
For the storage of the data, one of the ways to do so is by using the NSUserDefaults.
Once you have stored the user's data, you can access the NSUserDefaults from a different view without having to pass any objects between those views / controllers.
Generally you'll want to use properties and delegates to pass data between views.
As far as persisting data, for light-weight data (like preferences) use NSUserDefaults. For more complex data, use Core Data.
I have read several articles about UITableView, including the official doc and some on SO. But my situation seems to be different.
I want to update the Table each time the view loaded. And I must fetch the data using HTTP request.
What I got now is:
When enter the table view, I should use a non-synchronous HTTP request to update the data. Because I don't want the main thread to wait. One place to do that, is in the tableView:cellForRowAtIndexPath: method. So I return 0 for no data exist at the beginning.
When I get the HTTP respond, I update rows on main thread using beginUpdates endUpdates insertRowsAtIndexPaths:withRowAnimation:
And I must update the "Data Source" at the same time, but how to do that?
Or should I make a daemon thread and update my data every once in a while? So that the data will be ready when TableView is loaded.
You would do it like this:
Have a boolean or some variable where you can reliably detect whether you have all the data.
In viewWillAppear, reset everything. Start loading your data.
If you don't have the data yet, you only display one section with one cell (a placeholder cell that reads "Loading..." and shows a spinner, for instance).
Once the data is completely loaded, you set the bool or whatever.
Call [self.tableView reloadData];
In all of your UITableViewDataSource methods you would need to check whether you've got the data already or not. If not, you return the placeholder data.
[yourtablename reloadData]; will help you relaod the data in the tableview, You can call this once you get the response from your server
I'm not sure there's a "best method" for what you're trying to accomplish here. I would suggest trying the method you have, and seeing if it provides an adequate user experience (whatever that means to you) and if it doesn't, try something else. I would definitely suggest having some sort of "loading" indicator while the table is empty and waiting for http response.
In terms of your question about the "data source", the data source of a UITableView is simply an object that implements the UITableViewDataSource protocol which you can read about here. Often times, you will have XCode set up a UITableViewController object which will act as both delegate and data source to your table view. How you actually store your data is up to you. The data source protocol simply provides the methods by which a table view will "ask" for the data it needs to load.
In my UIView I've got a UITableView (UITV) which is controlled by an NSFetchedResultsController (NSFRC). The UIView is inside a UINavigationController.
When the view is about to be loaded/displayed I start some background activities which fetch data from a remote server (JSON) and parse into Core Data.
The NSFRC is being called when the parsing is done and the threaded NSManagedObjectContext have been merged into the main context.
The problem is that sometimes many rows are being inserted to Core Data at once, a lot of table cells are being added and there is quite a delay from that the actual fetching and parsing is done, until the rows are being displayed.
Now I wonder if anyone knows of any solution to, for example:
hook up a spinner to some "fetched results controller inserted all its rows for this time" (or something) notification/delegate call to at least tell the user that "something is going to show up soon"?
Or might the best solution simply be to not initialize the NSFRC until the background fetching and processing is completed?
Thanks!
If I understand your question correctly, you may want to look into the NSFetchedResultsControllerDelegate methods, with documentation available here: http://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html
There are delegate methods available for pre changes with controllerWillChangeContent:, post changes with controllerDidChangeContent and during changes with didChangeSection: and didChangeObject.
I hope it helps!
Rog
I'm new to this Core Data business.
I got a UITableViewController hooked up with a NSFetchedResultsController. In viewDidLoad, I fire a request to get necessary data from the server, then use [self.fetchedResultsController performFetch:&error] to update the table view. All works fine until that point.
Now I want to move the data fetching stuff to another thread, so after the app received a NSArray object from the server, it performs the didFinishFetchingItems selector on the main thread. In that selector, I save the NSArray to the Core Data store and have the fetchedResultsController perform a fetch. No data show up, although a NSLog reveals that the data is still there (e.g. [[fetchedResultsController fetchedObjects] count] returns 100). I have to put a [self.tableView reloadData] at the end of the method to refresh the table view manually.
My question is: What have I done wrong? Why did I need to do the table view refreshing manually?
You should not touch your NSFetchedResultsController in a non-main thread, that is not a thread-safe operation.
If you are having a long delay on fetching then you need to do a background fetch using a separate NSManagedObjectContext. If you perform a separate fetch in the background it will load the data into cache and then the NSFetchedResultsController will hit the cache instead of disk, speeding up retrieval on the main thread.
You do not need to refresh anything manually; fetchedResultsController does that for you.
What you need to do is to implement NSFetchedResultsControllerDelegate for some object, and set that object as the delegate for your fetchedresultscontroller.
See this about what you need to implement. If your model is simple, you can pretty much copy-paste that code into your delegate and everything works.
The important thing is to keep both the resultscontroller and other pieces of code working against the same managed object context. This is how the resultscontroller can pick up the changes. But, in Core Data guide, there are some caveats about multithreading, so make sure you have your threading bases covered and then all works.
I'm finishing up the Core Data tutorial, and it suggests trying to convert to using a NSFetchedResultsController. So I've got it so that I can query the existing data, but when I add a row at the beginning, tableView:cellForRowAtIndexPath calls NSFetchedResultsController.objectAtIndexPath, but that still returns the old zeroth object instead of the new one. Is there something I need to do to flush that data?
Have you set your view controller as the fetched results controller's delegate and implemented the NSFetchedResultsControllerDelegate protocol? If so, you should not have to perform the fetch again, the fetched results controller will invoke the delegate methods in response to changes.
(Note, though, the caution in NSFetchedResultsController documentation regarding the implementation of the table view data source methods.)
Nobody has answered yet, so I'll add my guess. It looks like this link might be relevant. The suggestion there is that calling either of these two methods should get an update for you:
-[NSManagedObjectContext processPendingChanges]
-[NSManagedObjectContext save]
Perhaps the documentation for NSManagedObjectContext will be useful.
There was a clue in the link that Naaf provided. Turns out that after doing the save, I needed to call -[NSFetchedResultsController performFetch] again.