How to disable caching from NSURLSessionTask
Asked Answered
K

8

62

In my iOS app, I am using NSURLSessionTask to download json data to my app. I discovered that when I call the url directly from the browser, I get an up to date json and when it's called from within the app, I get an older version of the json.

Is this due to caching? How can I tell NSURLSessionTask to not use caching.

This is the call I use:

NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

Thanks!

Kuban answered 20/6, 2014 at 13:29 Comment(1)
If you own the API server, you may want to consider fixing the caching headers on that end instead. The URLSessionTasks should be obeying the headers, so maybe something isn't being set right.Trilogy
C
90

If your read the links from @runmad you can see in the flow chart that if the HEAD of the file is unchanged it will still used the cached version when you set the cachePolicy.

In Swift3 I had to do this to get it to work:

let config = URLSessionConfiguration.default
config.requestCachePolicy = .reloadIgnoringLocalCacheData
config.urlCache = nil

let session = URLSession(configuration: config)

That got a truly non-cached version of the file, which I needed for bandwidth estimation calculations.

Creatine answered 10/3, 2017 at 15:47 Comment(4)
It's strange, I would've thought the urlCache is nil by default.Kuban
@VanDuTran From URLCache documentation : "For default sessions, the default value is the shared URL cache object." Meaning if you don't specify anything then it would just use the same cache that was available to you from shared sessionWay
Thanks man, it worked. Any idea how to remove/disable caching the db files in "Cache" folder? thank you again.Chemnitz
I don't know for some reason I still had to add ' URLCache.shared.removeAllCachedResponses()' soon after I receive the response in my session datatask completionHandler. It doesn't show the folder "fsCachedData" now and that's what I wanted.Chemnitz
D
40

Rather than using the sharedSession, you also can create your own NSURLSession using a NSURLSessionConfiguration that specifies a default cache policy. So, define a property for your session:

@property (nonatomic, strong) NSURLSession *session;

And then:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
self.session = [NSURLSession sessionWithConfiguration:configuration];

Then requests using that session will use that requestCachePolicy.

Donohoe answered 20/6, 2014 at 14:13 Comment(3)
This does not seem to work for me. At least not in iOS simulator. Tried turning internet connection off, but then it returns a cached reply. Please have a look at mu question #30324894Seattle
I see that we also need to set URLCache to nilViva
Can we either do what you wrote or just set cache to nil? Or we must include NSURLRequestReloadIgnoringLocalCacheData? Also why not just use an ephemeral session?Way
F
38

Swift 4 & 5

I know it's been a while, but in case it might help someone in the future.

You may also use .ephemeral configuration property of URLSession, which doesn't save any cookies and caches by default.

As documentation goes,

An ephemeral session configuration object is similar to a default session configuration, except that the corresponding session object doesn’t store caches, credential stores, or any session-related data to disk. Instead, session-related data is stored in RAM.

So, your code might look like this:

let configuration = URLSessionConfiguration.ephemeral
let session = URLSession(configuration: configuration)
Firestone answered 8/3, 2019 at 10:26 Comment(2)
Working in Swift 5Avilla
Worth noting, I think this still does store those things, just not to disk. They'll live for the duration of the session. To disable cookies, I had to set sessionConfiguration.httpShouldSetCookies = false.Hydroelectric
Q
8

Swift 3, Xcode 8

extension UIImageView {
func donloadImage(fromUrl url: URL) {
    let request = URLRequest(url: url, cachePolicy: URLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 60.0)
    URLSession.shared.dataTask(with: request) { (data, response, error) in
        guard
            let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
            let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
            let data = data, error == nil,
            let image = UIImage(data: data)
            else { return }
        DispatchQueue.main.async() { () -> Void in
            self.image = image
        }
    }.resume()
}
Querida answered 25/1, 2017 at 11:0 Comment(0)
P
5

The below code worked for me, the catch is setting URLCache to nil.

 NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    config.URLCache = nil;
Payne answered 16/9, 2016 at 5:41 Comment(0)
M
0

You need to set the cachePolicy on NSURLRequest, here's the documentation.

Here's some insight as to how caching works in general.

You can read about the specific enums you can use for specifying the cachePolicy here in particular:

enum
{
   NSURLRequestUseProtocolCachePolicy = 0,
   NSURLRequestReloadIgnoringLocalCacheData = 1,
   NSURLRequestReturnCacheDataElseLoad = 2,
   NSURLRequestReturnCacheDataDontLoad = 3,
};
typedef NSUInteger NSURLRequestCachePolicy;

For example, you would do:

NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
Meyer answered 20/6, 2014 at 13:57 Comment(1)
I am using NSURLSession.Kuban
S
0

I was getting cache image for same url .. so i have done this

imageView.imageFromUrl(self.shareData.userResponseData["photo"] as! String)

extension UIImageView {

public func imageFromUrl(urlString: String) {

    if let url = NSURL(string: urlString) {

        let request = NSURLRequest(URL: url, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData, timeoutInterval: 60.0)

        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {

            (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
            self.image = UIImage(data: data)

        }
    }
}

}

Sesame answered 3/9, 2015 at 11:44 Comment(0)
K
0

Used http method POST, like:

  var request = URLRequest(url: ulr)
  request.httpMethod = "POST"
Kan answered 1/1, 2022 at 8:29 Comment(1)
While this may work in some cases if the server doesn't care what method is used, it's hacky at best and there are better solutions that don't involve using inapplicable HTTP methods.Write

© 2022 - 2024 — McMap. All rights reserved.