If you are an iOS developer using Mattt Thompson’s ‘delightful networking framework’
AFNetworking (and if you aren’t,
what are you waiting for?), perhaps you have been been curious or confused about the caching mechanism employed and how you can tweak it to your advantage.
AFNetworking actually takes advantage of 2 separate caching mechanisms:
In order to understand how each caching system works, let’s look at how they are defined:
How AFImageCache Works
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
AFImageCache is a private implementation of
There is no customization that you can do outside of editing the implementation in the
UIImageView+AFNetworking category, directly.
It stores all accessed
UIImage objects into its
NSCache controls when the
objects are released. If you wish to observe when images are released, you can implement
Edit (03.14.14) :
Mattt Thompson has gratiously informed me that as of
AFImageCache is configurable. There is now a public setSharedImageCache method.
Here’s the full AFN 2.2.1 UIImageView+AFNetworking specification.
How NSURLCache Works
Enabled by Default, but Needs a Hand
Unfortunately, it has a tendency to hog memory and does not write to disk in its default configuration. To tame the beast and potentially add some persistance, you can simply declare a
NSURLCache in your app delegate like so:
1 2 3 4
Here we declare a shared
NSURLCache with 2mb of memory and 100mb of disk space
Setting the Cache Policy on NSURLRequest Objects
NSURLRequestUseProtocolCachePolicy: specifies that the caching logic defined in the protocol implementation, if any, is used for a particular URL load request. This is the default policy for URL load requests
NSURLRequestReloadIgnoringLocalCacheData: ignore the local cache, reload from source
NSURLRequestReloadIgnoringLocalAndRemoteCacheData: ignore local & remote caches, reload from source
NSURLRequestReturnCacheDataElseLoad: load from cache, else go to source.
NSURLRequestReturnCacheDataDontLoad: offline mode, load cache data regardless of expiration, do not go to source
NSURLRequestReloadRevalidatingCacheData: existing cache data may be used provided the origin source confirms its validity, otherwise the URL is loaded from the origin source.
Caching to Disk with NSURLCache
Cache-Control HTTP Header
Cache-Control header or the
Expires header MUST be in the HTTP response header from the server in order for the client to cache it (with the existence of the
Cache-Control header taking precedence over the
This is a huge gotcha to watch out for.
Cache Control can have parameters defined such as
long to cache before updating response), public / private access, or
no-cache (don’t cache response).
Here is a good introduction to HTTP cache headers.
Subclass NSURLCache for Ultimate Control
If you would like to bypass the requirement for a
Cache-Control HTTP header and want to define your own
rules for writing and reading the
NSURLCache given an
you can subclass
Here is an example that uses a
CACHE_EXPIRES value to judge how long to hold on to the cached response
before going back to the source:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
Now that you have your
NSURLCache subclass, don’t forget to initialize it in your AppDelegate in order to use it :
1 2 3 4
Overriding the NSURLResponse before caching
-connection:willCacheResponse delegate is a place to intercept and edit the
object created by
NSURLConnection before it is cached. In order to edit the
NSURLCachedResponse, return an edited mutable copy as follows (code from
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3 4
I wanted to write this blog post for the benefit of the iOS community, to summarize all of the information I found dealing with caching releated to
AFNetworking. We had an internal app loading a lot of images that had some memory issues and performance problems. I was tasked with trying to diagnose the caching behavior of the app. During this exercise, I discovered the information on this post through scouring the web and doing plenty of debugging and logging.
It is my hope that this post summarizes my findings and provides an opportunity for others with
AFNetworking experience to add additional information. I hope that you have found this helpful.