Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RESTful iOS app - When to update model - best practices

Let's look at a typical RESTful iOS app, let's say a contact app, main screen is the list of contacts, when tapping on a contact you get to the contact detail screen.

The contact list is obtained through a REST API, and the contact details through another API.

Which event would you use to trigger the call to those APIs:

  • viewDidAppear on both view controllers
  • viewWillAppear on both view controllers
  • From the main view controller, call the contact detail API before calling the pushViewController:detailViewController
  • Any other events?

Currently I am using viewWillAppear mostly for this kind of scenario, or viewDidAppear in some specific cases, but in an effort to standardize my coding practices, I would like to definitely settle on the pros/cons of those various approaches.

like image 204
JP Hribovsek Avatar asked Jan 28 '13 23:01

JP Hribovsek


2 Answers

It's partly a matter of preference. Since the API call will generate an unknown delay, the app should present UI that indicates it's busy. My preference is to have the UI do as much as possible before the request. (My naive model of cognition is that looking at the new VC's UI while it's fetching data will occupy user's mind for an instant, making the lag seem that much shorter).

So I favor paramaters to the VCs that describe the request - like the id of the contact to be fetched on the detail VC, and do the request on viewDidAppear (if the data isn't already cached or needs a refresh). In that method, put up some UI to indicate the fetch is happening, so it has the form:

- (void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear:animated];

    if (/* i don't have my model or it's out of date */) {
        // put up 'i am busy' UI
        MyRequestClass *request = // form a request that fetches my model
        [request runWithBlock:^(id result, NSError *error) {
            // i build my request classes to run with blocks simplifying the caller side
            // if it's a json request, then pass a parsed result back to this block
            // remove 'i am busy' UI
            if (!error) {
                // init my model from result
                // other parts of this class observe that the model changes and updates the UI
            } else {
                // present error UI
            }
        }];
    }
}
like image 179
danh Avatar answered Oct 18 '22 03:10

danh


Firstly, it's good practice to ensure your API interface and data access is happening outside of your view controllers in a separate data access class (or data controller - if you're already doing this then apologies, and ignore this paragraph). You want to avoid putting networking code directly into your view controller, because it's going to make your life very difficult if you either want to create an iPad specific view or need to revamp your UI in some way later on down the line).

With that out of the way, you have several options. In terms of performance from the user's perspective, it's best to pre-fetch as much from your RESTful API as you can. This is what libraries such as AFIncrementalStore that map your API to Core Data try to do. But if you have many thousands of contacts, are heavily rate limited, or bandwidth constrained this is going to be problematic.

What's absolutely certain is that you want to make the call to your networking API as soon as possible so that the user experiences minimal delay. You may find using viewDidLoad rather than viewWillAppear or viewDidAppear may work better in this case: you can set your view up with a loading/holding graphic or animation, trigger your asynchronous networking call, and then once complete display the required information.

like image 40
lxt Avatar answered Oct 18 '22 01:10

lxt