How to populate an UITableView when JSON response arrives? - ios

I am looking for a sample code, showing what is the best way to populate an UITableView with the response of JSON data. Let me explain in details.
The situation is the following:
When I navigate to the current view controller(the one with the table view), I send a request to my server in order to send me a JSON response. Meanwhile, I display an Activity indicator in foreground, showing the user that an activity is loading. When the response arrives, I need to parse it, store it with Core Data and then populate my Table View with the data.
My question is:
What is the best practice, best way to populate the table view? Should I grab the whole data that I need and use a NSArray while populating the table view? Or may be use NSFetchedResultsController for this purpose? How should I reload the table view? Is [self.tableView reloadData] good enough for my purpose?
I hope I was clear enough with my question(s) :) Thanks in advance

If the view controller always needs to call out to the server on every view, you can simply retain the response dictionary (or convert it to your own plain objects and retain an array of those) and bind the tableview in the afnetworking callback.
If you do not always need to call it, you could save the objects to core data on call back then create your retained NSFetchedResultsController and set the delegate on it (just in case the data gets modified/altered elsewhere).

Related

When to load data from Firebase

I'm using a cocoa pod called ACTabScrollView. In the demo code, it has a View Controller for the UI part which scrolls from side to side and has different tabs, and a view controller that has a table view (a "content view controller"). Each tab displays different information on each table view, but the information is sourced from a single array and is divided via an assigned enum. If this is confusing, there is a gif on the ACTabScrollView readme. In my "content view controller," I can hard code an array and it works flawlessly. The class for this content view controller has a variable declaration that I've never seen before as I'm new to iOS programming.
var category: TeamCategory? {
didSet {
for team in Team.teamArray {
if (team.category == category || category == .all) {
teamArray.append(team)
}
}
}
}
A project sample with this snippet is located here.
In the above snippet, Team is a model of teams, and the class has a hard coded array of teams (which are structs).
Obviously, I don't want to hard code the array of Teams in the app because I want to be able to update the array and have it update in real time. I'm using Firebase and I've tried loading the array in the App Delegate, in the UI view controller, and in the content view controller, but the tableView does not populate. I've confirmed that the data is arriving.
When/Where should I load the data from Firebase? The content view controller needs the array loaded before the view controller is loaded. Any tips for this would be much appreciated.
When you should load the data from Firebase is a design decision. You said that the content view controller needs to have the array loaded before the view controller is loaded, so you should request that data from Firebase at some point in your app flow where you can be guaranteed that the request will have come back with data before your TableView is attempting to load that data.
You may be running into a race condition where you are requesting the data, and then going to the content view controller before the request finished.
In general you don't want to have to rely on a guarantee that a request will finish in time, so I recommend doing what #rmaddy suggested, where you load the data before hand, and then have some sort of completion handler / notification / delegate call that will call reloadData on your tableView once the array from which you are pulling your data is updated.
The project sample you are referring to does not handle an asynchronous case, as you are handling. The didSet in the property declaration is just a closure that gets executed when you set a value for that property. In the case of the project sample, the news category is set at the time of the view controller instantiation, and then the didSet executes once and attaches the appropriate news array for the tableView to access. Again, in your case, as long as you are updating your array that contains your tableview's source of data after the data returns from Firebase, calling reloadData on your tableView should achieve the result you are looking for. If it doesn't, then that means you aren't properly updating that teamArray.

How to cancel Parse fetch data request

I'm using a PFQueryTableViewController from Parse.
I'm using a segmented control to retrieve two types of items from the database. Depending on which segmented button is selected, it retrieves one type or the other and reloads the same tableView. The problem is that when I am loading one type and then I switch to the other while the first is still loading, the tableView populates with items of the first type. Any way to cancel a tableView data retrieval?
The PFQueryTableViewController's data retrieval is handled by overriding queryForTable, you should be able to call cancel just as you would on any other query.
Alternatively, it is very easy to build your own table view controller which populates it's data source using Parse. Using this, you could maintain two separate query result containers to avoid conflicts between the two segments.
Here's another post which will show you how you could go about creating your own table view controller.

Loading Data Asynchronously into UITableView

I am using xCode 7 beta and swift, and storing my data using Parse.com. In which method in the UITableViewController should I be asking for data from my database? I need to ensure it is all present by the point in the lifecycle of the controller at which the cells need to be presented.
Is there anyway to guarantee this if I am loading data asynchronously?
viewDidLoad would be a good place for this but there might be a few second difference between displaying a blank tableView and when it gets populated depending on how long it takes to pull your data.
So in viewDidLoad you'll tell the Parse SDK to pull data and when it's complete, you can call [self.tableView reloadData]
You should be asking for your data before the tableview is shown. That way you can pass your cells the ParseObject within the cellForIndexPath function. Then within your cell you can go ahead and get other information from ParseObject such as fetching relations or PFFIles etc

How to "sync" UI with Core Data?

I would like to know what is the usual approach for syncing UI with Core Data, for example when you display data stored by Core Data in a table view, and you want to show additional info about an object when the user taps its cell in the table view, how would you link the table view cell to a specific object in Core Data ? I have seen many people not recommending to use IDs since Core Data wasn't designed in this way, but then what to use if we are not using an ID ? I would have wanted to do something like : "OK, the selected cell has this ID, let's go in Core Data fetch the object with the same ID" But if I'm not doing this, how can I do ?
Same question for other cases where you need this kind of link... in my case, I need a link between pins on a map and Core Data objects, so that I display additional info when the pin is tapped, a little bit like in Apple Maps for example...
What should I do ?
Thank you.
You can do that by using NSFetchedResultsController - you can subclass your UITableViewController from CoreDataTableViewController (.h .m) and the only method you need to override would be cellForRowAtIndexPath:. Then can access objects directly like this:
MyCustomObject *obj = [self.fetchedResultsController objectAtIndexPath:indexPath];
For your second question, when you are not using a table view there are two options. One you can fetch the object (assuming you are at the very top of the stack) or two, far more common, you have the NSManagedObject instance passed into you using simple dependency injection during the storyboard segue.
Any view that is below/after a table view should never need to fetch or call something like -objectWithID: as the object is already in memory and the controller that is giving you the ID already has the object. Just pass the object around like any other language.

how to create refresh button in UITableView

I want to create one application that read many data from json and show them in tableview.
I want to create one button that when to click on it this page for a second time to be refresh and take data from json (check json again and if this json changed tableview also changed)
I dont know how create this function that refresh this page and run code at first.
please tell me about it.
[self.tableView reloadData]
to load more data from webserver in to table
Put a button in header of section. I think that is the best place. In target method of that button call json and download all data. then call [self.tableView reloadData]. It will call all table methods like number of row , sections, cellForRow.
Why don't you use the Default RefreshControl provided in iPhoneSDK.
A UIRefreshControl object provides a standard control that can be used to initiate the refreshing of a table view’s contents. You link a refresh control to a table through an associated table view controller object. The table view controller handles the work of adding the control to the table’s visual appearance and managing the display of that control in response to appropriate user gestures.
Check this to learn about its implementation : Working with UIRefreshControl
You can place a UIToolBar above the tableview. In that you can have a barbutton, to which you could give an action to fetch the data again. Once the data fetch is done, call
[self.tableview reloadData];

Resources