Friday, January 18, 2013

Working with JSON more efficiently by creating models on demand

Earlier this week I posted a tutorial to show you how to use simple data models to consume data from an online JSON api from Kiva.org.
Now I am going to show you how you can lazy create all the models from the feed that you read from that same JSON API. The reason to do that might be that sometimes you will receive huge amounts of that back from the JSON APIs you use and therefore you would like to optimize your app’s performance by implementing lazy model loading. Let’s have a look at the setup and goal of this exercise.

The starter Kiva API project

You will need the completed tutorial from this post “How to fetch and parse JSON by using data models”. Either clone the project from GitHub here or first quickly go through the tutorial and then come back.

If you run the completed JSON_HelloWorld project you will get a complete dump of the list of the fetched loan models as they get dumped to the Xcode console by this line in viewDidAppear:

NSLog(@"loans: %@", _feed.loans);

Since JSONModel does all validation of the incoming JSON according to your data models – all the incoming data is converted to model instances in a one-shot operation.

However there might be cases where you would like to sacrifice the automatic validation and atomicity in favour of performance. To do that let’s quickly have a look at how do you use the KivaFeed model in this example.

  1. You fetch the JSON data from web,
  2. then you use the standard UITableView delegate methods to read from the loans array and visualise loan information in the table cells

However you can show only 10 – 11 cells at the same time, and especially if there are 1000+ elements in the loans array it might not make sense to initialise all the models, since the user might not ever scroll so further through the table view. Therefore you are good to split the 2 step process in two separate steps.

To do that you will use a feature of the JSONModel framework, that allows you to instantiate models in an array on demand (lazy creating). Let’s have a look at how to do that.

Convert on demand for JSON models

Open up KivaFeed.h and change the declaration of the loans property to:

@property (strong, nonatomic) NSArray<LoanModel, ConvertOnDemand>* loans;

What adding the “ConvertOnDemand” protocol does is that the model creates a JSONModelArray instead of an NSArray for the “loans” property. The JSONModelArray is a special NSArray sub-class that converts the standard JSON compliant object coming from the web to the corresponding JSONModel class at the time the index of the array is first accessed. This way effectively implementing lazy loading for the models in the array.

That was easy right?

However you still have the NSLog line in your viewDidAppear: method, which actually accesses every single model in the array in order to print its description in the XCode console. (Thus converting all JSON to models in one shot to print the array description in the console.)

Go ahead and remove the NSLog line – now you have JSONModel converting JSON to models only when the cell for the model is visible on the screen.

A proof for lazyness

However it is not easy to say whether the models are actually created on demand right? On the surface everything looks the same.

Let’s quickly code the proof!

Let’s hook to a JSONModel method called upon instantiation so we can print to the console when model instances are made.

Open up LoanModel.m and inside the empty implementation body add this method:

-(void)validate:(NSError**)err{    NSLog(@"Loan of %@", self.name);}

The validate: method is called at the very end of the model init method (you would normally use this method if you want to implement any custom data validation). However for this exercise you will use it to print the self.name property to show that the model is being created.

Hit Run now in Xcode and you will see something like this in your output console:

2013-01-17 18:17:09.287 JSON_HelloWorld[85586:c07] Loan of David2013-01-17 18:17:09.290 JSON_HelloWorld[85586:c07] Loan of Susana2013-01-17 18:17:09.291 JSON_HelloWorld[85586:c07] Loan of Robert2013-01-17 18:17:09.292 JSON_HelloWorld[85586:c07] Loan of Adjowa2013-01-17 18:17:09.292 JSON_HelloWorld[85586:c07] Loan of Kulsun2013-01-17 18:17:09.293 JSON_HelloWorld[85586:c07] Loan of Lerma2013-01-17 18:17:09.293 JSON_HelloWorld[85586:c07] Loan of Kristine2013-01-17 18:17:09.294 JSON_HelloWorld[85586:c07] Loan of Morris2013-01-17 18:17:09.294 JSON_HelloWorld[85586:c07] Loan of Naimjon2013-01-17 18:17:09.295 JSON_HelloWorld[85586:c07] Loan of Faustinas

(Note that you will see different set of names in your console.)

That’s 10 models created – matching the 10 visible table cells on the screen. Cool.

Now scroll down the table view and you will see new models being created as new cells come into the screen.

2013-01-17 18:18:28.706 JSON_HelloWorld[85586:c07] Loan of Las Palomas Group2013-01-17 18:18:28.724 JSON_HelloWorld[85586:c07] Loan of Ismoil2013-01-17 18:18:28.740 JSON_HelloWorld[85586:c07] Loan of Rustam2013-01-17 18:18:28.761 JSON_HelloWorld[85586:c07] Loan of Hamrokhon...etc.

Awesome! That’s exactly what you wanted.

So now you know how to create a model which can loads large amounts of JSON data and postpone the actual model creation to the time when the models are actually needed.

Cheers, Marin

The post was originally published on the following URL: http://www.touch-code-magazine.com/working-with-json-more-efficiently-by-creating-models-on-demand/

  ·



Source : touch-code-magazine[dot]com

0 comments:

Post a Comment