54

When I send a GET request twice with Alamofire I get the same response but I'm expecting a different one. I was wondering if it was because of the cache, and if so I'd like to know how to disable it.

Julian
  • 8,808
  • 8
  • 51
  • 90
Rémi Telenczak
  • 690
  • 1
  • 5
  • 9
  • 1
    For me none of the solutions below, or any that i found worked. Turned out, my hosting provider went through some changes and the JSON file was 'stuck' even though i would edit it, it always kept presenting the same file. Used another host and it worked. Probably few will have the same issue but it's worth noting. – Sam Bing Apr 13 '17 at 19:51

9 Answers9

52

You have a few options.

Disabling the URLCache Completely

let manager: Manager = {
    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    configuration.URLCache = nil
    return Manager(configuration: configuration)
}()

Configuring the Request Cache Policy

let manager: Manager = {
    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    configuration.requestCachePolicy = .ReloadIgnoringLocalCacheData
    return Manager(configuration: configuration)
}()

Both approaches should do the trick for you. For more information, I'd suggest reading through the documentation for NSURLSessionConfiguration and NSURLCache. Another great reference is NSHipster article on NSURLCache.

cnoon
  • 16,575
  • 7
  • 58
  • 66
  • 8
    Where should this code go? In app delegate? Please elaborate. – user3246173 Feb 26 '16 at 18:24
  • 1
    @user3246173 see [Alamofire#manager](https://github.com/Alamofire/Alamofire#manager) – He Yifei 何一非 Apr 06 '16 at 15:17
  • 1
    Doesn't work for me. And also after reading all content in the attached links I still don't know where to call this code. – Andrej Jul 26 '16 at 10:41
  • 2
    At some point "Manager" became "SessionManager" and some other things changed. Swift 3 version: `let manager: SessionManager = { let configuration = URLSessionConfiguration.default configuration.requestCachePolicy = .reloadIgnoringLocalCacheData return SessionManager(configuration: configuration) }()` – snakeoil May 24 '17 at 20:55
49

This is what worked for me.

NSURLCache.sharedURLCache().removeAllCachedResponses()

Swift 3

URLCache.shared.removeAllCachedResponses()
Allanah Fowler
  • 1,251
  • 16
  • 17
34

swift 3, alamofire 4

My solution was:

creating extension for Alamofire:

extension Alamofire.SessionManager{
    @discardableResult
    open func requestWithoutCache(
        _ url: URLConvertible,
        method: HTTPMethod = .get,
        parameters: Parameters? = nil,
        encoding: ParameterEncoding = URLEncoding.default,
        headers: HTTPHeaders? = nil)// also you can add URLRequest.CachePolicy here as parameter
        -> DataRequest
    {
        do {
            var urlRequest = try URLRequest(url: url, method: method, headers: headers)
            urlRequest.cachePolicy = .reloadIgnoringCacheData // <<== Cache disabled
            let encodedURLRequest = try encoding.encode(urlRequest, with: parameters)
            return request(encodedURLRequest)
        } catch {
            // TODO: find a better way to handle error
            print(error)
            return request(URLRequest(url: URL(string: "http://example.com/wrong_request")!))
        }
    }
}

and using it:

Alamofire.SessionManager.default
            .requestWithoutCache("https://google.com/").response { response in
                print("Request: \(response.request)")
                print("Response: \(response.response)")
                print("Error: \(response.error)")
        }
0x384c0
  • 2,256
  • 1
  • 17
  • 14
  • Agree! Thank you. I've made a requestWithCache function too and now I simply use the proper one. I think this should be included in Alamofire by default – rmvz3 Apr 23 '17 at 00:08
  • Works like a charm! – Konstantinos Natsios Jun 11 '17 at 09:12
  • 1
    This doesn't seem to work for me. Are you sure this prevents reading from cache and not just prevents writing to cache? So if there is still something in cache you'll get that anyway? I'm experiencing caching problems with the iTunes lookup that I use to check if there is a new app version: [https://itunes.apple.com/nl/lookup/?id=1234567890](https://itunes.apple.com/nl/lookup/?id=1234567890). Clearing the cache with removeAllCachedResponses() does work though. – Janneman Jun 30 '17 at 08:48
  • Can you please help me how to enable cache up to 3 Minutes using Alamofire? – Nikunj Kumbhani Nov 12 '18 at 10:47
  • Cache lifetime can be set on server side in Cache-Control: max-age=. To find out, how to do same thing using Alamofire, create another question on stackoverflow. – 0x384c0 Nov 16 '18 at 06:16
8
func getImage(url: String, completion: @escaping (UIImage?) -> ()) {

    let urlRequest = URLRequest(url: URL(string: url)!)
    URLCache.shared.removeCachedResponse(for: urlRequest)
    //URLCache.shared.removeAllCachedResponses()

    Alamofire.request(url).responseData { (dataResponse) in
        guard let data = dataResponse.data else {
            return completion(nil)
        }
        completion(UIImage(data: data, scale:1))
    }
}
Warif Akhand Rishi
  • 23,920
  • 8
  • 80
  • 107
2

In Alamofire 4 and Swift 3:

// outside function, inside class
var sessionManager: SessionManager!

func someFunc() {
    let configuration = URLSessionConfiguration.default
    configuration.urlCache = nil
    let sessionManager = Alamofire.SessionManager(configuration: configuration)
    sessionManager.request("http://example.com/get").responseJSON { response in
        // ...
    }
}
He Yifei 何一非
  • 2,592
  • 4
  • 38
  • 69
2

[This approach doesn't disable caching, it merely makes sure that cached files aren't reused]

An easier way to get past cache problem for a particular call is to just add a random number in the call params.

For Swift 3, you can use, arc4random() to generate a random number.

Nagendra Rao
  • 7,016
  • 5
  • 54
  • 92
  • Yes, not a good approach to stop call caching, but a quick way to avoid cached data for a particular call. Useful for testing, obviously not a solution to get rid of caching as each of the call with a random number would still get cached. – Nagendra Rao Jun 27 '17 at 17:02
2

I solved it by doing

configuration.urlCache?.removeAllCachedResponses()
iAnurag
  • 9,286
  • 3
  • 31
  • 48
2

You can try to add cache-control to your headers.

let headers = ["Authorization": "Bearer \(token)",
               "Cache-Control": "no-cache"]
elp
  • 8,021
  • 7
  • 61
  • 120
LoraKucher
  • 73
  • 6
1

Specifically removing a cached response before firing that request again would be more appropriate like:

let url = "http://google.com"
let urlRequest = URLRequest(url: URL(string: url)!)

URLCache.shared.removeCachedResponse(for: urlRequest)

Alamofire
  .request(urlRequest)
  .responseJSON(completionHandler: { response in
    //handle response
}
ardarda
  • 63
  • 5