-
-
Save kevindelord/35a0a098fbcabfb92259 to your computer and use it in GitHub Desktop.
How to integrate Etag in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let API_HEADER_FIELD_NONE_MATCH : String = "If-None-Match" | |
let API_HEADER_FIELD_ETAG : String = "Etag" | |
let API_REQUEST_SUCCESS : Int = 200 | |
func ETagForURL(urlString: String) -> String? { | |
// return the saved ETag value for the given URL | |
return NSUserDefaults.standardUserDefaults().objectForKey(urlString) as String? | |
} | |
func updateETag(urlResponse: NSURLResponse!) { | |
if let httpResponse = urlResponse as? NSHTTPURLResponse { | |
if let urlString = httpResponse.URL?.absoluteString { | |
if let etag = httpResponse.allHeaderFields[API_HEADER_FIELD_ETAG] as? String { | |
// save the etag header value with the url as a key. | |
NSUserDefaults.standardUserDefaults().setObject(etag, forKey: urlString) | |
NSUserDefaults.standardUserDefaults().synchronize() | |
} | |
} | |
} | |
} | |
func readFromBackend() { | |
let urlString = "https://herderbeten.s3.eu-central-1.amazonaws.com/impressum/imprint.html" | |
// create a mutable request | |
var request = NSMutableURLRequest(URL: NSURL(string: urlString)!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData, timeoutInterval: 60); | |
// add etag header value | |
if let etag = self.ETagForURL(urlString) { | |
request.addValue(etag, forHTTPHeaderField: API_HEADER_FIELD_NONE_MATCH) | |
} | |
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in | |
if (error != nil) { | |
UIAlertView(title: L("API_ERROR"), message: error.localizedDescription, delegate: nil, cancelButtonTitle: nil, otherButtonTitles:"ok").show() | |
} | |
if (response != nil) { | |
self.updateETag(response) | |
if let httpResponse = response as? NSHTTPURLResponse { | |
// Only update the entities if the status code is K_API_REQUEST_SUCCESS (200) and if there is no ERROR | |
// The status code could also be K_API_REQUEST_CACHED (304) depending on the etag status | |
if (httpResponse.statusCode == API_REQUEST_SUCCESS && error == nil && data != nil) { | |
// New data fetched | |
let htmlText = NSString(data: data, encoding: NSUTF8StringEncoding) | |
return | |
} | |
} | |
} | |
// An error occured OR nothing changed. The application should use cached data. | |
} | |
} | |
// MARK: - Write files to cache folder | |
func writeDataToFile(data: NSData, filename: String) { | |
if let path = self.getCacheDirectoryFilepath(filename) { | |
data.writeToFile(path, atomically: false) | |
self.addSkipBackupAttributeToItemAtURL(NSURL.fileURLWithPath(path as NSString)) | |
} | |
} | |
func getCacheDirectoryFilepath(filename: String) -> String? { | |
let directories : [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String] | |
if let cacheFolderPath = directories?.first { | |
return cacheFolderPath.stringByAppendingPathComponent(filename) | |
} | |
return nil | |
} | |
func addSkipBackupAttributeToItemAtURL(URL: NSURL!) -> Bool { | |
assert(NSFileManager.defaultManager().fileExistsAtPath(URL.path!)) | |
var error : NSError? = nil | |
var success : Bool = URL.setResourceValue(true, forKey: NSURLIsExcludedFromBackupKey, error: &error) | |
if (success == false || error != nil) { | |
println("Error excluding \(URL.lastPathComponent) from backup \(error) ") | |
} | |
return success | |
} |
Probably because cache could be lost but you could have a copy of some file locally that you don't need to update so you don't get too much traffic on your hosting. That's my case at least.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@kevindelord why do you need to do this all stuff when
NSURLRequest.CachePolicy.useProtocolCachePolicy
provides all sorts of implementation by default based on RFC 2616.https://developer.apple.com/documentation/foundation/nsurlrequest/cachepolicy/useprotocolcachepolicy
https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13