我正在使用一个使用以下标头响应的服务器:
Cache-Control: no-cache
last-modified: Mon, 17 Dec 2018 14:47:19 GMT
以下代码:
let myTask = URLSession.shared.dataTask(request: myRequest, completionHandler: { ... })
myTask.resume()
正确发送
If-Modified-Since
标头。
但是当我这样做时:
URLCache.shared.cachedResponse(for: myRequest)
我得到了
nil
结果,而:
URLCache.shared.getCachedResponse(for: myTask, completionHandler: { ... })
我在
nil
中得到了非 completionHandler
结果。
我本以为两者都会给我类似的结果。有人可以向我解释一下吗?
我知道这已经很老了,但鉴于这已经引起了一些关注,我想分享我的经验。我的问题是在设置请求标头之前我正在检查 URLCache。两个请求都需要有标头。如果不这样做,最终就会失败。我不确定有多少标题需要相等(如果有的话)。 AFAIK 两个请求都需要有标头存在,或者都没有标头
下面是异步工作示例,我们可以检查数据是否被缓存并返回缓存的数据
let token = "JWTToken"
let url = URL(string: "someWebsite")!
let headers = [
"Authorization": "Bearer \(token)",
"accept-language": "en-US",
]
var request = URLRequest(url: url)
request.allHTTPHeaderFields = headers
// Pull data from cache if exists
if let cachedResponse = URLCache.shared.cachedResponse(for: request) {
let myCachedResponseObject = try JSONDecoder().decode(MyCustomObject.self, from: cachedResponse.data)
} else {
print("No cached response")
}
// Else perform request
let (data, res) = try await URLSession.shared.data(for: request)
// ...
或者,我们可以修改请求以从缓存的响应中获取 ETag,并检查服务器以查看数据是否尚未修改(它将返回状态代码 304)(如果服务器设置为以这种方式工作)
if let cachedResponse = URLCache.shared.cachedResponse(for: request) {
if let response = cachedResponse.response as? HTTPURLResponse {
let headers = response.allHeaderFields
let etag = headers["Etag"] as? String ?? "-" // get the etag and cache control
let cc = headers["Cache-Control"] ?? "-" // policy from the headers
request.setValue(etag, forHTTPHeaderField: "if-none-match") // set our request
request.setValue(cc, forHTTPHeaderField: "cache-control") // headers to match it
}
} else {
print("No cached response")
}
let (data, res) = try await URLSession.shared.data(for: request) // perform request
if let response = (res as? HTTPURLResponse) {
if response.statusCode == 304 {
// Server told us no need to update data
print("\(response.statusCode) Not modified")
guard let cachedResponse = URLCache.shared.cachedResponse(for: request) else {
return // this should theoretically never hit because to get here there must've been existing cache for this request
}
let myResponseObject = try JSONDecoder().decode(MyCustomObject.self, from: cachedResponse.data) // decode the data from cache
} else {
print("Status: \(response.statusCode)")
}
}
// Server said its time to update our data
let myResponseObject = try JSONDecoder().decode(MyCustomObject.self, from: data) // decode the new data received from the server
URLCache.shared.removeCachedResponse(for: request) // Remove the old cached data
URLCache.shared.storeCachedResponse(CachedURLResponse(response: res, data: data), for: request) // store the newly received data in cache
请记住,这使用异步函数调用,因此您必须将整个内容包装在异步函数或
Task {}
组中
希望这有帮助:)