Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift NSURLRequestCachePolicy.UserProtocolCachPolicy要求_Swift_Nsurlsessionconfiguration_Nsurlrequestcachepolicy - Fatal编程技术网

Swift NSURLRequestCachePolicy.UserProtocolCachPolicy要求

Swift NSURLRequestCachePolicy.UserProtocolCachPolicy要求,swift,nsurlsessionconfiguration,nsurlrequestcachepolicy,Swift,Nsurlsessionconfiguration,Nsurlrequestcachepolicy,我使用以下代码进行缓存,从服务器收到的响应具有以下标题。是否有任何头需要从请求端设置,以便缓存在10秒的时间内工作 连接收到的Resopnse标头=[日期:Sat,2015年9月12日22:51:16 GMT,传输编码:身份,服务器:Apache Coyote/1.1, 内容类型:application/json;charset=UTF-8,过期日期:Sat,9月12日 2015年22:51:26 GMT,缓存控制:最大年龄=10,必须重新验证] 不缓存的强大代码 import UIKit c

我使用以下代码进行缓存,从服务器收到的响应具有以下标题。是否有任何头需要从请求端设置,以便缓存在10秒的时间内工作

连接收到的Resopnse标头=[日期:Sat,2015年9月12日22:51:16 GMT,传输编码:身份,服务器:Apache Coyote/1.1, 内容类型:application/json;charset=UTF-8,过期日期:Sat,9月12日 2015年22:51:26 GMT,缓存控制:最大年龄=10,必须重新验证]

不缓存的强大代码

import UIKit

class HTTPJSONDonwload: NSObject , NSURLConnectionDataDelegate , NSURLConnectionDelegate {
    static let httpjsonDownloader:HTTPJSONDonwload = HTTPJSONDonwload()

    func startDownload(){
        let serverRequest = getServerURL()

        NSURLConnection(request: serverRequest, delegate: self, startImmediately: true)
    }

    func getServerURL() -> NSMutableURLRequest{

        let request:NSMutableURLRequest = NSMutableURLRequest(URL:NSURL(string:"http://citiesfav-jcitiesj.rhcloud.com/Cache/getAllCities")! )
        request.cachePolicy = NSURLRequestCachePolicy.UseProtocolCachePolicy
        request.HTTPMethod = "POST"
        return request
    }

    func connection(connection: NSURLConnection, didReceiveData data: NSData) {

        print("Connection Data= \(NSString(data: data, encoding: NSUTF8StringEncoding))")
    }

    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
        print("Connection Received Resopnse Headers= \((response as! NSHTTPURLResponse).allHeaderFields)")
    }

    func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse? {
        print("Connection will cache Response")       
        return cachedResponse
    }
}
从标头中删除必须重新验证后,它仍在获取请求

连接接收到的Resopnse标头=[Cache Control:max age=10, 传输编码:身份,日期:2015年9月13日星期日18:35:43 GMT, 内容类型:application/json;字符集=UTF-8,服务器: ApacheCoyote/1.1,有效期:2015年9月13日星期日18:35:53 GMT]

后来的发现表明POST请求确实得到缓存,但与get不同,get考虑了最大年龄

func startDownload(){
    let serverRequest = getServerURL()
    let cache = NSURLCache.sharedURLCache()
    let response = cache.cachedResponseForRequest(serverRequest)

    if response != nil {
        serverRequest.cachePolicy = NSURLRequestCachePolicy.ReturnCacheDataDontLoad
    }

    NSURLConnection(request: serverRequest, delegate: self, startImmediately: true)
}
tl;博士 您需要使用
GET
而不是
POST

func getServerURL() -> NSMutableURLRequest{
    ...
    request.HTTPMethod = "POST"
    ...
}
冗长的解释 问题是您的请求是一篇
帖子

func getServerURL() -> NSMutableURLRequest{
    ...
    request.HTTPMethod = "POST"
    ...
}
通常,
POST
请求用于在服务器上创建(有时也用于更新)资源。对创建或更新请求重用缓存响应没有多大意义,因为无论如何都必须将请求发送到服务器(否则不会创建或更新任何内容)。似乎iOS会在
POST
请求时自动绕过缓存

然而,在您的特定情况下,您并不真正需要
POST
,因为您只是从服务器读取数据。这意味着您应该使用
GET
请求

func getServerURL() -> NSMutableURLRequest{
    ...
    request.HTTPMethod = "GET"
    ...
}
我用以下代码片段验证了iOS系统是否确实重用了缓存

let d = HTTPJSONDonwload()

// Initial request. Can not reuse cache.
d.startDownload()

// Subsequent request after 5 seconds. Should be able to reuse the cache.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(5 * NSEC_PER_SEC)), dispatch_get_main_queue()) {
    d.startDownload()
}

// Subsequent request after 11 seconds. Cannot reuse the cache because
// the expiration timeout is 10 seconds.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(11 * NSEC_PER_SEC)), dispatch_get_main_queue()) {
    d.startDownload()
}
当我在模拟器中运行此程序并使用Charles Proxy监视网络调用时,我确实只看到两个事件:

第一个调用是初始请求

第二次呼叫是延迟11秒后发出的第三次请求

请注意,5秒后发出的第二个请求没有出现,这意味着已从缓存中检索响应。但是,
NSURLConnection
的委托方法仍将被调用,就像响应来自网络一样。因此,通过代码中的日志输出,您将在控制台上看到所有三个请求

Connection Received Resopnse Headers= [Server: Apache-Coyote/1.1, Content-Type: application/json;charset=UTF-8, Keep-Alive: timeout=15, max=100, Proxy-Connection: Keep-alive, Date: Mon, 14 Sep 2015 06:28:05 GMT, Content-Encoding: gzip, Content-Length: 36, Cache-Control: max-age=10, Vary: Accept-Encoding]
Connection Data= Optional({"1":"New York"})
Connection will cache Response
Connection Received Resopnse Headers= [Server: Apache-Coyote/1.1, Content-Type: application/json;charset=UTF-8, Keep-Alive: timeout=15, max=100, Proxy-Connection: Keep-alive, Date: Mon, 14 Sep 2015 06:28:05 GMT, Content-Encoding: gzip, Content-Length: 36, Cache-Control: max-age=10, Vary: Accept-Encoding]
Connection Data= Optional({"1":"New York"})
Connection Received Resopnse Headers= [Server: Apache-Coyote/1.1, Content-Type: application/json;charset=UTF-8, Keep-Alive: timeout=15, max=99, Proxy-Connection: Keep-alive, Date: Mon, 14 Sep 2015 06:28:16 GMT, Content-Encoding: gzip, Content-Length: 36, Cache-Control: max-age=10, Vary: Accept-Encoding]
Connection Data= Optional({"1":"New York"})
Connection will cache Response

请注意,在第二个请求之后没有
连接将缓存响应
,因为该响应是从缓存中检索的,因此没有必要再次缓存它。

问题在于没有调用
WillCacheSponse
委托方法,或者后续请求不使用缓存的响应,而是使用缓存的响应从服务器重新加载?以前我使用的是NSURLSession,未调用WillCacheResponse。现在,我正在使用NSURLConnection,为此调用willCacheResponse。但是,它没有考虑10秒的时间,每次都从服务器获取数据。您是否尝试监视实际的网络呼叫?当您在10秒内再次启动请求时,它应发出
HEAD
请求以检查资源是否已更改。可能是您的服务器指示资源在其对
HEAD
请求的响应中发生了更改吗?服务器没有指示资源发生了更改,而是一个用于测试的固定json响应。如果请求在10秒内发送,那么客户端iOS本身应该从缓存返回数据,因为我有expires和max age的详细信息。你知道我可以在哪里部署.war,你可以从你这边检查它,因为你已经有了客户端代码。我想iOS会一直执行
请求,因为你的服务器在
缓存控制
头字段中返回
必须重新验证
。文档中说:如果内容必须重新验证,URL加载系统会向原始源发出HEAD请求,以查看资源是否已更改。如果未更改,则URL加载系统将返回缓存的响应。如果已更改,URL加载系统将从原始源获取数据。我怀疑这就是问题所在。如果您删除
必须重新验证
,会有什么不同吗?让工作正常。谢谢但是,随着我找到的帖子,它缓存,但不考虑年龄。我在我的问题中加了这个。@andyPaul我也注意到了。它可能会忽略指定的过期时间,因为它会自动假定POST请求不能或不应该被缓存。但是,在这种情况下,它也可以首先跳过缓存。不幸的是,我找不到任何涉及GET和POST请求处理的官方文档。