Scratching image table view controllers

The aim of this post is showing how to fix choppy tableviews when they are showing huge images fetched from the cloud.

 

The App

The app is very simple, just a table view that shows a collection of pictures.

Simulator Screen Shot 28 Aug 2016 17.03.55

The app presents the following problems:

  • The picture size is huge so the scroll must be smooth.
  • There is a high memory consumption, so iOS quick the app out.
  • The pictures are fetched every time that a cell is being presented (not cached).
  • Fetch is not cancelled once the cell is not shown in the tableview due to scroll.

filesizes

The picture resolution is 6144 x 4096.

 

The classical approach

Tableviews (and scrollviews) scroll must be smooth. User would not detect app bandwidth consumption easily, but a bumpy scroll is detected from the very beginning. Here what we have to do is to be sure that image is fetched in background and, once is retrieved, update image view in the main thread.

This is how a regular cell should have to be configured:

 

Memory consumption

But memory consumption increases in a dramatic (deadly) way:

MemoryConsumption

When you access the NSData, it is often compressed (with either PNG or JPEG). When you use the UIImage, there is an uncompressed pixel buffer which is often 4 bytes per pixel (one byte for red, green, blue, and alpha, respectively). There are other formats, but it illustrates the basic idea, that the JPEG or PNG representations can be compressed, when you start using an image is uncompressed.

This model does not work at all with huge pictures, it is  necessary to work with a different architecture.

The image provider

We will delegate the  work of fetching and processing the image to a image provider class. Every cell will has its own image provider.

imageprovider

We will create the image provider in tableview willDisplayCell method:

It could be the case that cell will dissapear before image provider ends its tasks. You can cancel the operation done by image provider.

In my case I was not interested in doing that because it was highly likely to get back to the dissapeared cell.

Cache the downloaded stuff.

At the end is only necessary to download the image once, not every time that cell is going to be shown. We have implemented this by using NSCache object, this differs from other mutable collections in a few ways:

  • It incorporates various auto-removal policies, which ensures that it does not use too much system memory.
  • You can access from different threads without having to lock the cache yourselve.
  • Retrieving something from an NSCache object returns an autoreleased result.
  • Unlike an NSMutableDictionary object, a cache does not copy the key objects that are put into it.

Profile new architecture

With new architecture the memory consumption lasts in that way:

newmetrics

Awesome, It has been reduced memory consumption by 60!!!

 

Conclusion

There are times that is not under app developer the image size of images that has to fetch. If you use the classical approach then you will find that tableview scroll is choppy and most probaly OS will kick the app out. For avoiding such disgusting issue this architecture fits properly well. You can find the source code here.

     

Model your classes with Argo JSON parser

The aim of this post is just basic introduction about how to use Argo framework for feeding your model classes from JSON data.

What is Argo.

[From https://github.com/thoughtbot/Argo]

Argo is a library that lets you extract models from JSON or similar structures in a way that’s concise, type-safe, and easy to extend. Using Argo, you won’t need to write validation code to ensure that incoming data is of the right type, or to make sure required data fields aren’t turning up empty. Argo uses Swift’s expressive type system to do that for you, and reports back explicit failure states in case it doesn’t find what you’ve told it to expect.

Argo

Argo is the Greek word for swift and the name of the ship used by Jason, son of Aeson, of the Argonauts. Aeson is the JSON parsing library in Haskell that inspired Argo, much like Aeson inspired his son Jason.

Codoapods. First things first.

In the Podfile you will have to add two frameworks, Argo itself and Curry that is being used for saving effort on initializing structs and classes.

 

Parsing structs

In this section through different examples I will explain how to parse the most common JSON structures.

Example 1. Most Basic JSON structure.

The content of the json file is the following:

The modeling struct is the following:

Just a few comments

  • As you can see with curry you save up call the initializer passing all class attributes.
  • <^> is for marking the first attribute, the rest are marked with a <*>
  • <| is for parsing a regular attribute and <|? for the optional ones.

For parsing just:

  • “person” is just the filename that contains the json.
  • JSONFromFile is a helper method that retrieves the json from the file. At the end of the post you will find a like for downloading whole sample project.

Example 2. 1-n attributes.

The content of the json file is the following:

The modeling struct is the following:

And this one:

Just a comment:

  • <|| is for parsing a collection of items

For parsing just:

Example 4. Another way of parsing JSON file.

The content of json file is the following:

The modeling struct:

For parsing the struct just:

As you can see the way of calling parser in that case is different but the result is exactly the same.

Parsing classes

For parsing classes I am based on the last struct example, but for clear understanding I will show an example.

This is the json content:

The modeling class:

In deep the idea is quite close than with structures, but in case of classes is carried out in a different way.

Finally for calling the parser:

Conclusion

I hope that throught all those examples you will not find any difficulty for understanting how to do a basic parsing. Please take a look at the library documentation for deeper understanding. You can download the sample project from here.

Usefull links