I am using Alamofire Framework for HTTP requests in my app. Even though by standard URLCaching is not ON, Alamofire sets it as default.
Caching
Caching is handled on the system framework level by NSURLCache.
https://github.com/Alamofire/Alamofire#caching
I understand that caching is important for performance (network, CPU etc.) but if caching is not expiring after some minutes, caching prevents the app from checking whether if the remote content has changed or not.
I also have read a lot of articles explaining how efficient method caching is and how recommended for use.
Then my question is, when will the cached data expire? Will it ever expire?
The cache will expire based on the 'Cache-Control' HTTP-Header contained within the response to the request.
NSURLSession uses NSURLCache for this, and since Alamofire uses NSURLSession under the hood, the Cache-Control header is what determines the expiry time.
Related
I've just come across something that has entirely changed my mental image of URLSession caching in iOS.
We were hitting an endpoint that only ever got hit once.
Restarting the app wouldn't hit the endpoint again.
Deleting the app would cause it to hit the endpoint again... but only once.
The header of the response contains...
Cache-Control public, max-age=1800
So it is down to caching. By manually telling the URLSession to ignore the cache it would hit the endpoint again.
In the docs it shows the caching policy and how it works as a workflow diagram.
https://developer.apple.com/documentation/foundation/nsurlrequestcachepolicy/nsurlrequestuseprotocolcachepolicy
But where is the cached data stored once the app is terminated? Surely the app and everything to do with it is removed from memory?
The URLSession is using URLCache for it's caching system. It's used for all network resources. You can access it directly or setting your own through URLSessionConfiguration. The underlying location of the URLCache is on the file system rather than in memory. There is a way to manage cache yourself though. Say, for instance, your response should be encrypted on the device. Slightly bad example, but you get the point. ;)
Here's an article how to manage cache programmatically if you are needing more control over caching.
Hi i have read about cache policy but still not quite clear. My purpose is to set request cache 3 minutes. Response cache 3 minutes. keep old cache for 1 day. What is the implementation that we should we use? Is there any setting that we can change beside those default bellow? (I use AFNetworking 3 for request and response). Any help is much appreciate. Thanks
NSURLRequestCachePolicy
NSURLRequest has a cachePolicy property, which specifies the caching behavior of the request according to the following constants:
NSURLRequestUseProtocolCachePolicy: Caching logic defined in the protocol implementation is used for a particular URL load request. This is the default policy.
NSURLRequestReloadIgnoringLocalCacheData: Data should be loaded from the originating source. No existing cache data should be used.
NSURLRequestReloadIgnoringLocalAndRemoteCacheData: Not only should the local cache data be ignored, but proxies and other intermediates should be instructed to disregard their caches so far as the protocol allows.
NSURLRequestReturnCacheDataElseLoad: Existing cached data should be used, regardless of its age or expiration date. If there is no existing data in the cache corresponding to the request, the data is loaded from the originating source.
NSURLRequestReturnCacheDataDontLoad: Existing cache data should be used, regardless of its age or expiration date. If there is no existing data in the cache corresponding to the request, no attempt is made to load the data from the originating source, and the load is considered to have failed, (i.e. “offline” mode).
NSURLRequestReloadRevalidatingCacheData: Existing cache data may be used provided the origin source confirms its validity, otherwise the URL is loaded from the origin source.
You should almost invariably use NSURLRequestUseProtocolCachePolicy unless you're trying to kill caching entirely for some reason.
The cache durations should be set by the server as part of its response (in the Cache-Control header). The iOS URL cache obeys the policies specified in that header.
I've used NSURLRequestReturnCacheDataElseLoad but it does not work, ie, it always loads data from server as every time the data I received is different.
I'm wondering that:
even with NSURLRequestReturnCacheDataElseLoad policy, it also obeys the cache control headers from server's response, regardless of document saying ignoring expire date?
What is the storage policy for [NSURLCache sharedURLCache]? If it is in memory only, then next time I start the app it won't have cache on disk?
I found this very interesting:
NSURLRequestReturnCacheDataElseLoad not loading from cache on first request?
which says
it seems this problem only exists when there's a query in the url.
Is that a confirmed problem?
Thanks
Well this topic is almost 5 years old, but I just recently had the same problem. In my case, I was using a NSURLSessionDownloadTask which, according to Can I use HTTP caching with an NSURLSessionDownloadTask on iOS?, doesn't use caching no matter which caching policy is used. I switched my code to use NSURLSessionDataTask and the NSURLRequestReturnCacheDataElseLoad policy worked as expected.
I am downloading WMS tiles which I want to cache. I'm using AFNetworking which includes NSURLCache. The responses from the server do not contain Cache-Control protocols in the header.
I asked the server guy about this and was unfamiliar with server side cache-control. At the moment, he is swamped with other work. Do I need him to implement the cache-control or can I force NSURLCache to cache them w/out the info the response header?
Is NSURLCache persistent? If so, how can I clear the cache? The tiles will need to be retrieved per session and can not be persistent.
Or should I create my own cache?
When you activate NSURLCache it will work for any request that is based on the NSUrlRequest (like AFNetworking). The moment you activate the NSURLCache you can specify it's maximum size. You can also clear the cache by calling the removeAllCachedResponses or removeCachedResponsesForRequest methods. If the server does not send any cache control information, then the cache will still cache the file. If you want complete control over the cache, you could create your own cache. If you would like to see a sample code for that, then have a look at https://github.com/evermeer/EVURLCache
I was looking at Chirpy for css/js minifying,compression, etc.
I noticed it doesn't support caching. It doesn't have any logic for sending expires headers, etags, etc.
The absence of this feature made me question if caching content is not as much of a concern; YSlow! grades this so I'm a little confused. Now I'm researching caching and cannot explain why this css file, SuperFish.css, is being retrieved from cache.
Visit http://www.weirdlover.com (developer of Chirpy)
Look at initial network track. Notice, there is no expiration header for SuperFish.css.
Revisit the page and inspect the network trace again. Now SuperFish.css is retrieved from cache.
Why is the SuperFish.css retrieved from cache upon revisiting the page? This happens even when I close all instances of chrome and then revisit the page.
This seems to fall with in the HTTP specification.
13.4 Response Cacheability
Unless specifically constrained by a cache-control (section 14.9) directive, a caching system MAY always store a successful response (see section 13.8) as a cache entry, MAY return it without validation if it is fresh
13.2.2 Heuristic Expiration
Since origin servers do not always provide explicit expiration times, HTTP caches typically assign heuristic expiration times, employing algorithms that use other header values (such as the Last-Modified time) to estimate a plausible expiration time.
It would seem by not providing a cache-control header, and leaving out the expires header the client is free to use a heuristic to generate an expiry date and then caches the response based upon that.
The presence of an etag has no effect on this since the etag is used to re-validate an expired cache entry, and in this case chrome considers the cached entry to be fresh (the same applies to last-modified), thus it hasn't yet expired.
The general principle being if the origin server is concerned with freshness it should explicitly state it.
In this case (when server doesn't return Expires header), the browser should make HTTP request with If-Modified-Since header, and if the server returns HTTP 304 Not modified then the browser gets the data from the cache.
But, I see, nowadays browsers don't do any requests when the data is in the cache. I think they behave this way for better response time.