Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent my HTTP Get request from being cached in Swift?

Tags:

swift

I'm having a weird bug that pop up out of no where. I'm almost done with my app and I'm testing it, and then I noticed the data isn't being updated. The database gets updated, and I can hit the url directly and see the data is being returned from the server correctly, but when I print the data in Swift, it doesn't change.

Once I rerun the app it will change (most of the time)

I'm using Alamofire, but I've also tried two other methods:

let url = NSURL(string: "http://www.stackoverflow.com")
let request = NSURLRequest(URL: url!)

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
    println(NSString(data: data, encoding: NSUTF8StringEncoding))
}

and

let url = NSURL(string: "http://www.stackoverflow.com")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
    println(NSString(data: data, encoding: NSUTF8StringEncoding))
}

task.resume()

All 3 print out the same data.

I'm guessing it's a caching problem in Swift, but I haven't set anything to tell Swift to cache the data, and it's been working fine for the last few weeks.

The only thing I've done today was make a Git repo for my project.

Does anyone have any idea what could be causing this?


*edit:

Using Abhi Beckert's answer I tried this:

Conforming to the delegate NSURLConnectionDelegate

Adding:

func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse?
{
  return nil // never cache anything. ever.
}

and then to make the call:

let url:NSURL! = NSURL(string: "http://coffee.datausadev.com/api/getCoffeeBrands")
let request = NSURLRequest(URL: url, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 60)

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
    println(NSString(data: data, encoding: NSUTF8StringEncoding))
}

This method still didn't work.

like image 816
Kolby Avatar asked Feb 04 '15 01:02

Kolby


People also ask

How do I disable HTTP caching?

Here's how... When you're in Google Chrome, click on View, then select Developer, then Developer Tools. Alternatively, you can right click on a page in Chrome, then click Inspect. Click on the Network tab, then check the box to Disable cache.

DOES GET request get cached?

By enabling the caching of GET requests, you can improve the response times of requests for resource data that were previously submitted by the same user. When caching is enabled, the data is retrieved from the browser cache instead of from the business object on the server.

Can HTTP control caching?

The Cache-Control HTTP header field holds directives (instructions) — in both requests and responses — that control caching in browsers and shared caches (e.g. Proxies, CDNs).

What is HTTP cache-control?

Cache-control is an HTTP header used to specify browser caching policies in both client requests and server responses. Policies include how a resource is cached, where it's cached and its maximum age before expiring (i.e., time to live).


2 Answers

You need to set your controller object as the delegate for the NSURLConnection:

let request = NSURLRequest(URL: requestURL, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 60)
self.currentConnection = NSURLConnection(request: request, delegate: self)

This also requires making self conform to the data source:

class MyController: NSURLConnectionDataDelegate {

And disable caching with the relevant delegate method:

func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse?
{
  return nil // never cache anything. ever.
}

The .ReloadIgnoringLocalCacheData option on the URL request will disable reading the cache, and the willCacheResponse delegate method disables writing to the cache. You need to use both of them.

Unfortunately this means you cannot use the sendAsynchronousRequest convenience method and block callback - instead you'll have to use the delegate methods in NSURLConnectionDataDelegate to process the response. Basically you've got to create an NSMutableData object, and append to it as data comes in from the connection, until the connection tells you the request is finished or failed — then you can do something with the data.

As far as I know, it is impossible to fully disable caching while using sendAsynchronousRequest. You might want to create a wrapper class around NSURLConnection to make your code neater.

like image 100
Abhi Beckert Avatar answered Oct 08 '22 06:10

Abhi Beckert


I tired everything, was not helpfull . This solution Worked For me in (Swift 3)

I called destroyCache() function after every HttpResponse.

 public static func destroyCache() {
        let fileManager = FileManager.default
        let documentsUrl =  fileManager.urls(for: FileManager.SearchPathDirectory.cachesDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first! as NSURL
        let documentsPath = documentsUrl.path
        let bundleIdentifier = Bundle.main.bundleIdentifier! as String
        do {
            if let documentPath = documentsPath
            {
                let fileNames = try fileManager.contentsOfDirectory(atPath: "\(documentPath)/\(bundleIdentifier)")
                for fileName in fileNames {
                    let filePathName = "\(documentPath)/\(bundleIdentifier)/\(fileName)"
                    try fileManager.removeItem(atPath: filePathName)
                }
            }

        } catch {
            print("Could not clear: \(error)")
        }
    }
like image 21
nikhil Avatar answered Oct 08 '22 06:10

nikhil