NSURLCache and ETags
yes it does handle it transparently if you set its cache mode:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval:60];
note: you cannot see the header in the request at all and if a 304 response is returned by the server you will only see the 200 response that it transparently loaded from the cache.
How to clear cached response and ETag info when using NSURLCache?
This is an HTTP protocol thing, not a RestKit thing, so you need to look at the underlying handling / storage. So, I would expect your code to work. I don't think AFNetworking creates its own cache instance, but it might - it's worth checking in the code.
You could create the NSURLRequest
to send using RestKit and then set the cachePolicy
to NSURLRequestReloadIgnoringLocalAndRemoteCacheData
.
How to use NSURLSession to determine if resource has changed?
I created a HTTPEntityFingerprint structure which stores some of the entity headers: Content-MD5
, Etag
, and Last-Modified
.
import Foundation
struct HTTPEntityFingerprint {
let contentMD5 : String?
let etag : String?
let lastModified : String?
}
extension HTTPEntityFingerprint {
init?(response : NSURLResponse) {
if let httpResponse = response as? NSHTTPURLResponse {
let h = httpResponse.allHeaderFields
contentMD5 = h["Content-MD5"] as? String
etag = h["Etag"] as? String
lastModified = h["Last-Modified"] as? String
if contentMD5 == nil && etag == nil && lastModified == nil {
return nil
}
} else {
return nil
}
}
static func match(first : HTTPEntityFingerprint?, second : HTTPEntityFingerprint?) -> Bool {
if let a = first, b = second {
if let md5A = a.contentMD5, md5B = b.contentMD5 {
return md5A == md5B
}
if let etagA = a.etag, etagB = b.etag {
return etagA == etagB
}
if let lastA = a.lastModified, lastB = b.lastModified {
return lastA == lastB
}
}
return false
}
}
When I get an NSHTTPURLResponse
from an NSURLSession
, I create an HTTPEntityFingerprint
from it and compare it against a previously stored fingerprint using HTTPEntityFingerprint.match
. If the fingerprints match, then the HTTP resource hasn't changed and thus I do not need to deserialized the JSON response again; however, if the fingerprints do not match, then I deserialize the JSON response and save the new fingerprint.
This mechanism only works if your server returns at least one of the 3 entity headers: Content-MD5
, Etag
, or Last-Modified
.
More Details on NSURLSession and NSURLCache Behavior
The caching provided by NSURLSession
via NSURLCache
is transparent, meaning when you request a previously cached resource NSURLSession
will call the completion handlers/delegates as if a 200 response occurred.
If the cached response has expired then NSURLSession will send a new request to the origin server, but will include the If-Modified-Since
and If-None-Match
headers using the Last-Modified
and Etag
entity headers in the cached (though expired) result; this behavior is built in, you don't have to do anything besides enable caching. If the origin server returns a 304 (Not Modified), then NSURLSession
will transform this to a 200 response the application (making it look like you fetched a new copy of the resource, even though it was still served from the cache).
eTag support using Alamofire 4
By default, caching is ON. If you log HTTP traffic inside your app, you might see cached responses, without the app making requests to server this time.
In case when URLSession
decides to return cached response instead of going to server you will see same Date
HTTP response header.
To ensure caching is working, you should inspect network packets between your app and server.
Related Topics
How to Print Out a Property's Contents Using Xcode Debugger
Cllocationmanager Authorization Issue iOS 8
iOS Facebook Login "Given Url Is Not Allowed by the Application Configuration"
Avplayer with Playback Controls of Avplayerviewcontroller
Multiple Uitableview in Single Viewcontroller
Get Index or Tag Value from Imageview Tap Gesture
How to Access User Defined Runtime Attribute from the 'Sender' Object
iOS Automatic @Synthesize Without Creating an Ivar
How to Cancel Usernotifications
Confirm Back Button on Uinavigationcontroller
How to Remove the Bottom Gap of Uipageviewcontroller
Check If 3D Touch Is Supported and Enabled on the iOS9 Device
Mapkit Annotations Disappearing
iOS - Using Storyboard and Autolayout to Center the Uiscrollview
Bypass Code Signing with Xcode 6
Swift - How to Open Specific View Controller When Push Notification Received