如何防止我的HTTP Get请求被缓存在Swift中?

时间:2015-02-04 01:46:35

标签: swift

我有一个奇怪的错误,从那里突然出现。我差不多完成了我的应用程序,我正在测试它,然后我注意到数据没有更新。数据库得到更新,我可以直接点击url并看到正确地从服务器返回数据,但是当我在Swift中打印数据时,它不会改变。

一旦我重新运行应用程序,它将会改变(大部分时间)

我正在使用Alamofire,但我还尝试了其他两种方法:

let url = NSURL(string: "http://www.stackoverflow.com")
let request = NSURLRequest(URL: url!)

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
    println(NSString(data: data, encoding: NSUTF8StringEncoding))
}

let url = NSURL(string: "http://www.stackoverflow.com")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
    println(NSString(data: data, encoding: NSUTF8StringEncoding))
}

task.resume()

所有3个都打印出相同的数据。

我猜测它是Swift中的一个缓存问题,但是我没有设置任何东西来告诉Swift缓存数据,并且它在过去的几周内一直运行良好。

我今天唯一做的就是为我的项目做一个Git回购。

有没有人知道造成这种情况的原因是什么?


*编辑:

使用Abhi Beckert的回答我试过了:

符合代表NSURLConnectionDelegate

添加:

func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse?
{
  return nil // never cache anything. ever.
}

然后拨打电话:

let url:NSURL! = NSURL(string: "http://coffee.datausadev.com/api/getCoffeeBrands")
let request = NSURLRequest(URL: url, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 60)

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
    println(NSString(data: data, encoding: NSUTF8StringEncoding))
}

此方法仍然无效。

3 个答案:

答案 0 :(得分:1)

这不是Swift错误。

在幕后NSURLSession遵循某些策略,具体取决于支持它的配置对象。

默认配置(您通过sharedSession单例使用的配置)使用“当前设置的全局NSURLCache,NSHTTPCookieStorage和NSURLCredentialStorage对象,并基于默认配置”,通过NSUrlSession Reference

您的选择:

  1. 使用几乎无法缓存的“短暂”配置(想想隐私浏览模式),

  2. 自行设置配置并将缓存和其他策略设置为适合您需要的配置。

  3. 不要忘记考虑服务器的策略。请查阅文档,或者如果没有,请尝试根据您收到的http标头做出最佳决策,以响应您的请求。

    编辑:我现在才注意到您最初使用的是Alamofire。所有这些(以及Objective-c中的AF)确实提供了一个方便的,更高级别的做法,与iOS7之前的NSURLSession和NSURLConnection相同。他们都必须让你自定义缓存,浏览他们的文档。

答案 1 :(得分:1)

您需要将控制器对象设置为NSURLConnection

的委托
let request = NSURLRequest(URL: requestURL, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 60)
self.currentConnection = NSURLConnection(request: request, delegate: self)

这还需要使自我符合数据源:

class MyController: NSURLConnectionDataDelegate {

使用相关的委托方法禁用缓存:

func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse?
{
  return nil // never cache anything. ever.
}

URL请求中的.ReloadIgnoringLocalCacheData选项将禁用读取缓存,willCacheResponse委托方法禁用写入缓存。你需要同时使用它们。

不幸的是,这意味着您无法使用sendAsynchronousRequest便捷方法并阻止回调 - 相反,您必须使用NSURLConnectionDataDelegate中的委托方法来处理响应。基本上你必须创建一个NSMutableData对象,并在数据从连接进入时附加到它,直到连接告诉你请求完成或失败 - 然后你可以对数据做一些事情。

据我所知,使用sendAsynchronousRequest时无法完全禁用缓存。您可能希望在NSURLConnection周围创建一个包装类,以使您的代码更整洁。

答案 2 :(得分:1)

我厌倦了一切,没有帮助。这个解决方案适用于我( Swift 3)

我在每个HttpResponse之后调用了 destroyCache()函数。

 public static func destroyCache() {
        let fileManager = FileManager.default
        let documentsUrl =  fileManager.urls(for: FileManager.SearchPathDirectory.cachesDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first! as NSURL
        let documentsPath = documentsUrl.path
        let bundleIdentifier = Bundle.main.bundleIdentifier! as String
        do {
            if let documentPath = documentsPath
            {
                let fileNames = try fileManager.contentsOfDirectory(atPath: "\(documentPath)/\(bundleIdentifier)")
                for fileName in fileNames {
                    let filePathName = "\(documentPath)/\(bundleIdentifier)/\(fileName)"
                    try fileManager.removeItem(atPath: filePathName)
                }
            }

        } catch {
            print("Could not clear: \(error)")
        }
    }