How to approach 'caching' in iOS development with Swift

arauter picture arauter · Nov 17, 2016 · Viewed 10.8k times · Source

I am facing some issues in terms of what caching mechanism to implement for my iOS application. First, lets explain my situation.

I want to request thousands of nearby locations records (10000 and more) through a RESTful API on my server using Alamofire, where each record consists of a bunch of strings. The JSON response format looks similar to this:

[
   {
     "id": 1,
     "name": "Name x",
     "lat": 59.5025878,
     "lng": -0.1509515,
     "address": "Address x"
   },
   {
     "id": 2,
     "name": "Name y",
     "lat": 61.5025878,
     "lng": -0.1508515,
     "address": "Address y"
   },

   etc.

 ]

The key is that I only want to send/resend this query when the application launches or after a certain amount of time has passed or when the app user moved his/her location considerably that it would also change the nearby locations. In order to keep the server load low I am planning to do search queries on returned locations inside the app instead of querying the server for every single request, which would be really inefficient and costly.

As a result, I want to cache my response data on the phone but I don't know what option to go with. I did some background reading on both CoreData and NSCache. CoreData would allow me to store the location results in a database. This has the benefit that stored records stay alive internally, since it is a permanent storage solution after all. On the other side, using CoreData might be a complete overkill as it comes with an overhead and keeping the location records in cache using NSCache would probably not use much memory (remember I am storing just strings). But then again, why keeping location data in the cache, when user might not even access them that often. Also, there is the chance that location entries in the cache will be freed up to save up more memory.

I am sure there are other solutions out there that might even be better suited for my purpose. After all, I am quite new to this topic in iOS, hence I would really appreciate some guidance.

Thank you in advance.

Answer

Ryan H. picture Ryan H. · Nov 19, 2016

You are on the right track with considering CoreData and NSCache.

There will be tradeoffs. In reducing your network activity, you will be looking to utilize device memory and/or the file system. Usage of any of these resources should be carefully considered. All of the options below are viable and it may be worthwhile to do some measuring with instruments to see the impact of each approach.

On paper here is how I would weigh them given your requirements.

NSCache

Pros

  • Simple API, low effort to implement
  • Easy to reason about

Cons

  • If the data that you need is no longer cached then you will have to fire another network request. That said, you could implement the NSCacheDelegate and respond when an “object is about to be evicted or removed from the cache.” see NSCacheDelegate

Core Data

Pros

  • Can be used as an in-memory store (not just for persisting data to disk)
  • Can scale to accommodate more complex data modelling, querying and storage requirements
  • Has Xcode tooling support

Cons

  • Initially it would require more effort to implement than the other options
  • As mentioned by Duncan C, there is a learning curve
  • Adds another abstraction that may require more thought down the road than either the NSCache or plist

File System (plist or some other format)

Pros

  • Low effort to implement
  • Easy to reason about

Cons

  • Introduces file system I/O operations. From a performance standpoint this is not desirable if there are other options.
  • Doesn’t easily scale (if your needs change)