为什么我不能将收到的(通过 alamofire 呼叫)令牌放在我的 swift 应用程序的钥匙串中



我有一个网络服务,它向我返回一些数据,如nameloginauth_token。到目前为止,我正在 NSUserDefaults 中保存namelogin。现在我也想安全地存放auth_token,所以我决定把它放在钥匙串里。为此,我决定使用 https://github.com/matthewpalmer/Locksmith 这个插件。

到目前为止,我的代码如下所示:

Alamofire.request(.POST, "(serverURL)/authorization", parameters: params)
    .validate()
    .response { (request, response, data, error) in
        if(error != nil){
            print("error = (error)") 
        }else{
            let username = json["name"]
            let login = json["login"]
            let auth_token = json["auth_token"]
            let defaults =  NSUserDefaults.standardUserDefaults()
            defaults.setObject(login, forKey: "login")
            defaults.setObject(username, forKey: "username")
            defaults.synchronize() 
            let sb = UIStoryboard(name: "Main", bundle: nil)
            if let tabBarVC = sb.instantiateViewControllerWithIdentifier("TabController") as? TabController {
                self.window!.rootViewController = tabBarVC
            }
        }
}

但是当我添加这一行时:

 try Locksmith.saveData(["auth_token": json["auth_token"]], forUserAccount: "my_auth_token") 

紧接着:

 let defaults =  NSUserDefaults.standardUserDefaults()

然后我在Alamofire.request

时出错:
Cannot call value of non-function type 'NSHTTPURLResponse?'

所以我的问题是 - 如何在钥匙串中保存来自网络服务的auth_token

你遇到的是类型不匹配,不幸的是,AlamoFire Request类既有一个名为response的函数,又有一个名为response的属性(类型为NSHTTPURLResponse?,看起来很熟悉=))

在你的代码中,你调用try,这需要将封闭/函数标记为throws,或者你必须将代码包装在一个do-catch

因此,swift 编译器所做的是推断您正在编写的闭包已throws作为其定义的一部分。这显然不符合应该传递给func response的闭包的定义,所以它尝试了它能找到的另一个response,即属性。然后它完全失败,因为您无法尝试"调用"可选类型。

您应该在闭包中添加一个 do-catch 来处理锁匠可能抛出的错误。

编辑:回应您的评论。您只需将该调用包装在 do catch 中即可正确处理错误。有关 Swifts 错误处理模型的详细信息,请参阅 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html。

至于要捕获哪个错误,只需浏览一下锁匠 API,它就可以抛出从钥匙串 API 收到的错误。幸运的是,他们已经定义了他们在这里抛出的错误:https://github.com/matthewpalmer/Locksmith/blob/master/Source/LocksmithError.swift

作为要写的内容的一个例子,它就是这样

Alamofire.request(.POST, "(serverURL)/authorization", parameters: params)
    .validate()
    .response { (request, response, data, error) in
        if(error != nil){
            print("error = (error)") 
        }else{
            let username = json["name"]
            let login = json["login"]
            let auth_token = json["auth_token"]
            let defaults =  NSUserDefaults.standardUserDefaults()
            do {
                try Locksmith.saveData(["auth_token": json["auth_token"]], forUserAccount: "my_auth_token")
            } catch {
                // Handle the error, however you best see fit
                print("Error trying to save to keychain (error)")
            }
            defaults.setObject(login, forKey: "login")
            defaults.setObject(username, forKey: "username")
            defaults.synchronize() 
            let sb = UIStoryboard(name: "Main", bundle: nil)
            if let tabBarVC = sb.instantiateViewControllerWithIdentifier("TabController") as? TabController {
                self.window!.rootViewController = tabBarVC
            }
        }
}

最新更新