Search code examples
jsonios4asynchronousuitableview

Set UITableViewCell data from remote JSON file


I have UITableView representing list of cities (100 cities).

For each city I want to call specific remote(URL) JSON to get city's weather information and populate response data for each city cell in the UITableView.

When I run application, I want to see my table as fast as possible, so I don't need to wait for all json responses. I want that informations got asynchronously (when specific json is loaded, set it's information for corresponding city cell in the UITableView).

Note: It is important for me to call seperate remote JSON files.


Which technic is the best for this task?


Solution

  • I would start with the following approach:

    Create a data structure to hold city information, including:

    • path to your data service,
    • service call "state" (idle, waiting, completed, error),
    • weather information (from JSON returned by service call)

    When you first show the table, you will want to:

    • initialize your array (of the aforementioned data structure),
    • initiate each service call asynchronously,
    • set each row (city) state to waiting.

    You will also probably want to return a custom UITableCellView with the city name (if you already have it) and a spinning activity indicator. This will be your best option to have a fast load time (not waiting for services to complete) and give some visual indication that the data is loading.

    Each service call should use the ViewController as its delegate; you will need a key field so that when the services return, they can identify with which row/city they are associated.

    As each service completes and calls the delegate, it will send the data to the ViewController, which (in turn) will update the array and initiate a UITableView update.

    The UITableView update is, in my opinion, the most difficult part. Typically cells are drawn or updated when they become visible; the table pre-fetches all visible cells' geometry and then queries the actual contents when it's ready to draw each cell; as a result, your strategy for updating cells will depend on how your table is used.

    • If your cell geometry changes, you will most likely need to redraw your entire table; I shudder to think about what 50 simultaneous UITableView redraws will do for your app, so you might need to set a time-threshold to "chunk" updates and handle drawing more intelligently.
      [theTableView reloadData] will cause the entire table to be re-queried and redrawn.

    • If your cell geometry does not change, you can try to be more surgical of updating only the visible cells (the non-visible ones aren't an issue since their data will be queried when they become visible).
      [theTableView visibleCells] returns an array of visible cells; when your service call returns, you could update the data and then search the array to see if the cell in question is visible; if it is, you will probably need to send the specific UITableCellView a setNeedsDisplay message.

    There is a good explanation of setNeedsDisplay, setNeedsLayout, and 'reloadData' at http://iosdevelopertips.com/cocoa/understanding-reload-repaint-and-re-layout-for-uitableview.html.

    There is a relevant SO question at How to refresh UITableViewCell?

    Lastly, you will probably want to implement some updating logic in the service delegate error routine, just so you don't create endlessly spinning activity indicators.