【问题标题】:How to disable the URLCache completely with Alamofire如何使用 Alamofire 完全禁用 URLCache
【发布时间】:2016-09-28 20:38:31
【问题描述】:

在 Swift 中使用 Xcode 7.3 iOS 9.2 没有那么可怕的 Objective C 我已经为此工作了一段时间,现在已经绕着街区转了三遍。我在这里尝试过这篇文章,但没有用 http://www.mzan.com/article/32199494-alamofire-how-remove-cache.shtml

我也尝试过使用苹果文档,但这太糟糕了,我无法理解是否。

所以我正在做的是对我的服务器进行两次 Alamofire 调用。一是测试登录信息的凭据,看输入是否正确。二是下载并返回客户信息以供查看。当我第一次调用它时,两者都工作正常。问题是当我注销应用程序时,我从页面中清除了所有用户信息。但是当我在同一个会话中登录时,它会正确调用第一个,所以如果我输入错误的用户名或密码,即使我第一次正确登录,它也会返回 false。但是当我下载客户数据时,它一直在下载我第一次访问用户信息时的旧信息。它使用新的用户名和密码,但仍然下载旧的东西。

这是我的登录和注销功能:

//MARK: ButtonControllers
@IBAction func onLoginClick(sender: AnyObject) {

    errorMessageUI.text = "Checking Creditials"
    email = userNameInput.text!
    password = passwordInput.text!
    buildLoginUrl = checkLoginUrl + emailTag + email + passwordTag + password
    print(buildLoginUrl)
    print("Login Cred")
    checkLoginCredentials(buildLoginUrl)
}

@IBAction func onLogoutClick(sender: AnyObject) {

    //null out everything for logout
    email = ""
    password = ""
    self.loginInformation.setObject(self.email, forKey: "email")
    self.loginInformation.setObject(self.password, forKey: "password")
    self.loginInformation.synchronize()
    performSegueWithIdentifier("logoutSegue", sender: self)
    //self.view = LoginView
}

这是alamofire的电话

//MARK: Check Credentials Method
//Function to log into the server and retrive data
func checkLoginCredentials(myUrl : String)
{
    Alamofire.request(.GET, myUrl)
        .validate(statusCode: 200..<300)
        .responseString { response in
            print("Cred Success: \(response.result.isSuccess)")
            print("Cred Check: \(response.result.value)")
            //clear all url chache
            NSURLCache.sharedURLCache().removeAllCachedResponses()

            if response.result.value != nil
            {
                let checker : String = response.result.value!
                if checker.lowercaseString.rangeOfString("false") != nil {
                    self.canILogin = false
                    self.errorMessageUI.text = "Wrong username or Password try again"
                }else{
                    self.canILogin = true
                    print("Downloading Json file for customer info")
                    self.loadingImage.hidden = false
                    self.downlaodCustomerinfo(self.customerInfoUrl, myUser: self.email, myPass: self.password)
                    //defaults.setBool(textColorSwitch.on, forKey: "DarkText")
                    self.loginInformation.setObject(self.email, forKey: "email")
                    self.loginInformation.setObject(self.password, forKey: "password")
                    self.loginInformation.synchronize()
                }

                print("Login? " + self.canILogin.description ?? "none" )
            }else
            {
                //Stop the program from downloading anything to avoid crashes
                self.loadingImage.hidden = true
                print("I cannot download User Info")
                self.errorMessageUI.text = "A connection error occured"
                //set the json to be empty to avoid a crash
                //reset the json file incase there is anythig in it
                self.downloadJson = ""


            }

    }
}//end of checkLoginCredentials function

//MARK: Download Customer Infoamtion
func downlaodCustomerinfo(myUrl : String, myUser : String, myPass : String)
{

    //clear all url chache
    NSURLCache.sharedURLCache().removeAllCachedResponses()
    print("Username: " + myUser)
    print("Password: " + myPass)
    print("Download Url: " + myUrl )
    print("Jsonfile before download: " + self.downloadJson)
    Alamofire.request(.GET, myUrl)
        .authenticate(user: myUser, password: myPass)
        .validate(statusCode: 200..<300)
        .responseString { response in
            //print("Success: \(response.result.isSuccess)")
            print("Info Download: \(response.result.value)")


            if response.result.value != nil{

                self.downloadJson = response.result.value!
                print("Json file: " + self.downloadJson)
                self.parseCustomerInfo(self.downloadJson)
            }else
            {
                self.loadingImage.hidden = true
                print("I cannot download User Info")
                self.errorMessageUI.text = "A connection error occured"
                //set the json to be empty to avoid a crash
                self.downloadJson = "{}"
            }

    }
}//end of download

更新代码: 导致系统从 Alamofire 响应中返回 false

  //Create a non-caching configuration.
    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    config.requestCachePolicy = .ReloadIgnoringLocalAndRemoteCacheData
    config.URLCache = nil
    //Create a manager with the non-caching configuration that you created above.
    let manager = Alamofire.Manager(configuration: config)

    print("Username for download: " + myUser)
    print("Password: " + myPass)
    manager.request(.GET, myUrl)
        .authenticate(user: myUser, password: myPass)
        .validate(statusCode: 200..<300)
        .responseString { response in
            //print("Success: \(response.result.isSuccess)")
            print("Info Download: \(response.result.value)")

            if response.result.value != nil{

                self.downloadJson = response.result.value!
                print("Json file: " + self.downloadJson)
                self.parseCustomerInfo(self.downloadJson)
            }else
            {
                self.loadingImage.hidden = true
                print("I cannot download User Info")
                self.errorMessageUI.text = "A connection error occured"
                //set the json to be empty to avoid a crash
                self.downloadJson = "{}"
            }

    }


}//end of downloadCustomer function

【问题讨论】:

  • 是的,我检查了服务器在其中发送的头文件 Cache-Control →no-cache, no-store, max-age=0, must-revalidate 就像另一个帖子建议的那样问题
  • 你的Manager 在更新的代码中let manager = Alamofire.Manager(configuration: config) 的这一行,死了。您的经理在请求开始时不再存在(如果它开始)。您的请求失败,因为当您的经理超出范围时,请求将被取消。你应该做print("Error: \(response.result.error)") 看看它打印了什么。我这样做是有原因的self.manager = Alamofire.Manager(configuration: config)。这将保留经理并让请求有机会运行。一旦管理器解除分配,所有待处理的请求都会自动取消。
  • 我明白你在说什么,但是我如何在代码主体中声明一个管理器:Alamofire.Manager,靠近大多数其他变量的位置?
  • 使用dispatch_once 块创建一个static instance。在答案中添加了一个示例。

标签: ios swift alamofire nsurlsession nsurlcache


【解决方案1】:

为什么不配置会话?如果正确配置会话,将不会有缓存。

例子:

//Create a non-caching configuration.
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.requestCachePolicy = .ReloadIgnoringLocalAndRemoteCacheData
config.URLCache = nil

//Allow cookies if needed.     
config.HTTPCookieStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage()


//Create a manager with the non-caching configuration that you created above.
self.manager = Alamofire.Manager(configuration: config)


//Examples of making a request using the manager you created:

//Regular HTML GET request:
self.manager.request(.GET, "https://stackoverflow.com")
    .validate(statusCode: 200..<300)
    .validate(contentType: ["text/html"])
    .responseString { (response) in
        guard response.result.isSuccess else {
            print("Error: \(response.result.error)")
            return
        }
    print("Result: \(response.result.value)")
}


//JSON GET request:
self.manager.request(.GET, "someURL", parameters: params, encoding: .URL, headers: headers)
    .validate(statusCode: 200..<300)
    .validate(contentType: ["application/json"])
    .responseJSON { (response) in
        guard response.result.isSuccess else {
            print("Error: \(response.result.error)")
            return
        }

        print(response.result.value as? [String: AnyObject])
}

编辑:

let manager = {() -> Alamofire.Manager in
    struct Static {
        static var dispatchOnceToken: dispatch_once_t = 0
        static var instance: Alamofire.Manager!
    }

    dispatch_once(&Static.dispatchOnceToken) {
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        config.requestCachePolicy = .ReloadIgnoringLocalAndRemoteCacheData
        config.URLCache = nil

        let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage()
        config.HTTPCookieStorage = cookies
        Static.instance = Alamofire.Manager(configuration: config)
    }

    return Static.instance
}()

manager.request(.GET, "https://stackoverflow.com")
    .validate(statusCode: 200..<300)
    .validate(contentType: ["text/html"])
    .responseString { (response) in
        guard response.result.isSuccess else {
            print("Error: \(response.result.error)")
            return
        }
    print("Result: \(response.result.value)")
}

附:您还可以查看:

NSURLSessionConfiguration.ephemeralSessionConfiguration() - 返回一个 不使用持久存储进行缓存的会话配置, cookie 或凭据。

【讨论】:

  • 顶部?顶部是您初始化管理器的地方。顶部进行配置,然后使用该配置创建一个 Manager 对象。从那时起,所有不需要缓存的请求都应该使用该管理器。
  • 小心。我的例子是使用.responseJSON。您在 OP 中的代码使用.responseString。你也有不同的验证。我的代码还需要严格的contentType。你的没有。
  • 是的,它有所作为。我添加了另一个不同类型请求的示例。重要的是您使用您创建的管理器。您不必使用示例请求。
  • 非常感谢您的帮助,我很感激它带我解决了这个问题,并在它是一个有用的工具时教我关于调度的知识
  • reloadIgnoringLocalAndRemoteCacheData "重要此常量未实现,不应使用。" => developer.apple.com/reference/foundation/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 2019-12-11
  • 2017-10-13
相关资源
最近更新 更多