如何在Alamofire中禁用缓存

55

使用Alamofire发送两次GET请求时,我收到了相同的响应,但我期望得到不同的响应。我想知道是否是因为缓存造成的,如果是,我想知道如何禁用它。


1
对我来说,下面的解决方案以及我发现的任何解决方案都没有起作用。结果是,我的托管提供商经历了一些变化,JSON文件“卡住”了,即使我编辑它,它仍然保持相同的文件。使用另一个主机就可以了。可能很少有人会遇到同样的问题,但值得注意。 - Sam Bing
9个回答

53

你有几个选择。

完全禁用URLCache

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

配置请求缓存策略

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

这两种方法都可以解决你的问题。如需更多信息,建议阅读NSURLSessionConfigurationNSURLCache的文档。另一个很好的参考资料是NSHipster有关NSURLCache的文章。


8
这段代码应该放在哪里?是放在应用程序委托中吗?请详细说明。 - user3246173
1
@user3246173 请查看Alamofire#manager - He Yifei 何一非
1
对我不起作用。并且在阅读了附加链接中的所有内容后,我仍然不知道在哪里调用此代码。 - Andrej
2
在某个时候,“Manager”变成了“SessionManager”,还有其他一些变化。Swift 3版本:let manager: SessionManager = { let configuration = URLSessionConfiguration.default configuration.requestCachePolicy = .reloadIgnoringLocalCacheData return SessionManager(configuration: configuration) }() - snakeoil

49

这是对我有效的方法。

NSURLCache.sharedURLCache().removeAllCachedResponses()

Swift 3

URLCache.shared.removeAllCachedResponses()

1
我可以确认这个有效。每次在进行网络调用之前,都需要调用上述代码。 - Andrej
1
@Andrej,相比之下我只是在AppDelegate的didFinishLaunchWithOptions中调用了它。 - Venkatesh Chejarla

34

Swift 3,Alamofire 4

我的解决方案是:

为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")!))
        }
    }
}

并使用它:

Alamofire.SessionManager.default
            .requestWithoutCache("https://google.com/").response { response in
                print("Request: \(response.request)")
                print("Response: \(response.response)")
                print("Error: \(response.error)")
        }

同意!谢谢。我也写了一个 requestWithCache 函数,现在我只是使用正确的函数。我认为这应该默认包含在 Alamofire 中。 - rmvz3
像魔法一样运作! - Konstantinos Natsios
1
这对我似乎没有起作用。你确定这是防止读取缓存而不是仅仅防止写入缓存吗?所以如果缓存中仍然有东西,你仍会得到那个东西?我在使用 iTunes 查找时遇到了缓存问题,我用它来检查是否有新的应用程序版本:https://itunes.apple.com/nl/lookup/?id=1234567890。使用 removeAllCachedResponses() 清除缓存确实有效。 - Janneman
请问您能帮我解决如何使用Alamofire启用3分钟的缓存吗? - Nikunj Kumbhani
缓存生命周期可以在服务器端通过Cache-Control: max-age =设置。要了解如何使用Alamofire执行相同操作,请在stackoverflow上创建另一个问题。 - 0x384c0

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))
    }
}

2
我通过以下方式解决了这个问题。
configuration.urlCache?.removeAllCachedResponses()

2

[这种方法并不会禁用缓存,它只是确保缓存文件不被重复使用]

解决特定调用的缓存问题的更简单方法是在调用参数中添加一个随机数。

对于Swift 3,您可以使用arc4random()来生成随机数。


是的,停止调用缓存不是一个好方法,但可以快速避免特定调用的缓存数据。这对于测试非常有用,但显然不能解决缓存问题,因为每个带有随机数的调用仍将被缓存。 - Nagendra Rao

2
在Alamofire 4和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
        // ...
    }
}

对于上面的评论:https://github.com/Alamofire/Alamofire/issues/157 - Paul Slm
与 https://dev59.com/_VwY5IYBdhLWcg3wyqaH#32230328 相同,但更新答案而不是重复。 - Nike Kov

2
您可以尝试在标头中添加缓存控制。
let headers = ["Authorization": "Bearer \(token)",
               "Cache-Control": "no-cache"]

1

具体来说,在再次发出请求之前清除缓存的响应会更加合适,如下所示:

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
urlRequest.cachePolicy = .reloadIgnoringCacheData 已生效。 - Tancrede Chazallet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接