响应为 header `Cache-Control:Private` 的文件是否会被阻止缓存在 NSURLCache 中?
Would a file with a response header `Cache-Control:Private` be prevented from being cached in a NSURLCache?
是否会阻止响应为 header Cache-Control:Private
的文件缓存在 NSURLCache
中?共享缓存(如 setSharedCache
和 NSURLCache.sharedCache()
)或自定义缓存?
为了扩展,我需要在离线时访问 UIWebView
。这个 WebView
的来源有多个外部 CSS 和与之关联的 JS 文件。我可以缓存网站的大部分内容(CSS 等看起来就位),但它似乎没有缓存为网站提供重要信息的特定 JavaScript 文件。我注意到不会缓存的文件与其余文件之间的区别是它的 Cache-Control 设置为私有(其他是 public)。但是,根据我的阅读,将缓存控制设置为私有是为了防止在代理上进行缓存。它会影响 iOS 上的缓存吗?
设置缓存
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let URLCache: NSURLCache = NSURLCache(memoryCapacity: 10 * 1024 * 1024,
diskCapacity: 50 * 1024 * 1024,
diskPath: nil)
NSURLCache.setSharedURLCache(URLCache)
println("Disk cache usage: \(NSURLCache.sharedURLCache().currentDiskUsage)")
//
sleep(1)
return true
}
使用缓存
func getWebPage(onCompletion: (NSString, NSURL) -> Void) {
let url = getApplicationSelectorURL()
let request = NSURLRequest(URL: url, cachePolicy: .ReturnCacheDataElseLoad, timeoutInterval: 10.0)
let queue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler: { response, data, error in
println("Web page task completed")
var cachedResponse: NSCachedURLResponse
if (error != nil) {
println("NSURLConnection error: \(error.localizedDescription)")
if let cachedResponse = NSURLCache.sharedURLCache().cachedResponseForRequest(request) {
if let htmlString = NSString(data: cachedResponse.data, encoding: NSUTF8StringEncoding) {
onCompletion(htmlString, url)
} else {
println("htmlString nil")
}
} else {
println("cacheResponse nil")
}
} else {
cachedResponse = NSCachedURLResponse(response: response, data: data, userInfo: nil, storagePolicy: .Allowed)
NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
if let htmlString = NSString(data: data, encoding: NSUTF8StringEncoding) {
onCompletion(htmlString, url)
} else {
println("htmlString nil")
}
}
})
}
填充 UIWebView
APICommunicator.sharedInstance.getWebPage({ htmlString, url in
dispatch_async(dispatch_get_main_queue(),{
self.webView.loadHTMLString(htmlString, baseURL: url)
})
})
是的,NSURLCache
不缓存具有私有缓存控制策略的响应。 RFC #2616 表示
private:
Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache. This allows an origin server to state that the specified parts of the
response are intended for only one user and are not a valid response for requests by other users. A private (non-shared) cache MAY cache the response.
嗯,NSURLCache
使用 sharedCache,您甚至在发布的代码中设置了它。我想它几乎解释了一切。
解决方案是更改服务器行为,或者覆盖 NSURLCache
class 的某些方法。 (例如,您可以重写 header client-side,但这应该是一个非常糟糕的 hack。)
我最终创建了一个类似于 NSURLConnectionDelegate
方法 willCacheResponse
的方法,并替换了 Cache-Control:private
header.
willCacheResponse 方法
func willCacheResponse(cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse?
{
let response = cachedResponse.response
let HTTPresponse: NSHTTPURLResponse = response as NSHTTPURLResponse
let headers: NSDictionary = HTTPresponse.allHeaderFields
var modifiedHeaders: NSMutableDictionary = headers.mutableCopy() as NSMutableDictionary
modifiedHeaders["Cache-Control"] = "max-age=604800"
let modifiedResponse: NSHTTPURLResponse = NSHTTPURLResponse(
URL: HTTPresponse.URL!,
statusCode: HTTPresponse.statusCode,
HTTPVersion: "HTTP/1.1",
headerFields: modifiedHeaders)!
let modifiedCachedResponse = NSCachedURLResponse(
response: modifiedResponse,
data: cachedResponse.data,
userInfo: cachedResponse.userInfo,
storagePolicy: cachedResponse.storagePolicy)
return modifiedCachedResponse
}
调用方法
if let cachedResponse = self.willCacheResponse(
NSCachedURLResponse(response: response,
data: data,
userInfo: nil,
storagePolicy: .Allowed)) {
NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
}
现在离线时也能正确显示。真是一段旅程。
是否会阻止响应为 header Cache-Control:Private
的文件缓存在 NSURLCache
中?共享缓存(如 setSharedCache
和 NSURLCache.sharedCache()
)或自定义缓存?
为了扩展,我需要在离线时访问 UIWebView
。这个 WebView
的来源有多个外部 CSS 和与之关联的 JS 文件。我可以缓存网站的大部分内容(CSS 等看起来就位),但它似乎没有缓存为网站提供重要信息的特定 JavaScript 文件。我注意到不会缓存的文件与其余文件之间的区别是它的 Cache-Control 设置为私有(其他是 public)。但是,根据我的阅读,将缓存控制设置为私有是为了防止在代理上进行缓存。它会影响 iOS 上的缓存吗?
设置缓存
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let URLCache: NSURLCache = NSURLCache(memoryCapacity: 10 * 1024 * 1024,
diskCapacity: 50 * 1024 * 1024,
diskPath: nil)
NSURLCache.setSharedURLCache(URLCache)
println("Disk cache usage: \(NSURLCache.sharedURLCache().currentDiskUsage)")
//
sleep(1)
return true
}
使用缓存
func getWebPage(onCompletion: (NSString, NSURL) -> Void) {
let url = getApplicationSelectorURL()
let request = NSURLRequest(URL: url, cachePolicy: .ReturnCacheDataElseLoad, timeoutInterval: 10.0)
let queue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler: { response, data, error in
println("Web page task completed")
var cachedResponse: NSCachedURLResponse
if (error != nil) {
println("NSURLConnection error: \(error.localizedDescription)")
if let cachedResponse = NSURLCache.sharedURLCache().cachedResponseForRequest(request) {
if let htmlString = NSString(data: cachedResponse.data, encoding: NSUTF8StringEncoding) {
onCompletion(htmlString, url)
} else {
println("htmlString nil")
}
} else {
println("cacheResponse nil")
}
} else {
cachedResponse = NSCachedURLResponse(response: response, data: data, userInfo: nil, storagePolicy: .Allowed)
NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
if let htmlString = NSString(data: data, encoding: NSUTF8StringEncoding) {
onCompletion(htmlString, url)
} else {
println("htmlString nil")
}
}
})
}
填充 UIWebView
APICommunicator.sharedInstance.getWebPage({ htmlString, url in
dispatch_async(dispatch_get_main_queue(),{
self.webView.loadHTMLString(htmlString, baseURL: url)
})
})
是的,NSURLCache
不缓存具有私有缓存控制策略的响应。 RFC #2616 表示
private: Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache. This allows an origin server to state that the specified parts of the response are intended for only one user and are not a valid response for requests by other users. A private (non-shared) cache MAY cache the response.
嗯,NSURLCache
使用 sharedCache,您甚至在发布的代码中设置了它。我想它几乎解释了一切。
解决方案是更改服务器行为,或者覆盖 NSURLCache
class 的某些方法。 (例如,您可以重写 header client-side,但这应该是一个非常糟糕的 hack。)
我最终创建了一个类似于 NSURLConnectionDelegate
方法 willCacheResponse
的方法,并替换了 Cache-Control:private
header.
willCacheResponse 方法
func willCacheResponse(cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse?
{
let response = cachedResponse.response
let HTTPresponse: NSHTTPURLResponse = response as NSHTTPURLResponse
let headers: NSDictionary = HTTPresponse.allHeaderFields
var modifiedHeaders: NSMutableDictionary = headers.mutableCopy() as NSMutableDictionary
modifiedHeaders["Cache-Control"] = "max-age=604800"
let modifiedResponse: NSHTTPURLResponse = NSHTTPURLResponse(
URL: HTTPresponse.URL!,
statusCode: HTTPresponse.statusCode,
HTTPVersion: "HTTP/1.1",
headerFields: modifiedHeaders)!
let modifiedCachedResponse = NSCachedURLResponse(
response: modifiedResponse,
data: cachedResponse.data,
userInfo: cachedResponse.userInfo,
storagePolicy: cachedResponse.storagePolicy)
return modifiedCachedResponse
}
调用方法
if let cachedResponse = self.willCacheResponse(
NSCachedURLResponse(response: response,
data: data,
userInfo: nil,
storagePolicy: .Allowed)) {
NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
}
现在离线时也能正确显示。真是一段旅程。