为什么我不能将收到的(通过 alamofire 调用)令牌放入我的 swift 应用程序的钥匙串中?
Why I cannot put the received (by the alamofire call) token in the keychain in my swift app?
我有一个网络服务 returns 我有一些数据,例如 name
、login
和 auth_token
。到目前为止,我在 NSUserDefaults 中保存了 name
和 login
。现在我也想安全地存储 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
class 有一个名为 response
的函数,还有一个属性 称为 response
(类型 NSHTTPURLResponse?
,看起来很熟悉 =))
在您的代码中调用 try
,这需要将封闭的 closure/function 标记为 throws
,或者您必须将代码包装在 do-catch
中
所以 swift 编译器所做的是推断您正在编写的闭包将 throws
作为其定义的一部分。这显然与应该传递给 func response
的闭包定义不匹配,因此它尝试 other response
它可以找到的 属性。然后它就完全失败了,因为你不能尝试 'call' 一个可选类型。
您应该在闭包中添加一个 do-catch 来处理 Locksmith 可能抛出的错误。
编辑:回应您的评论。您只需要将该调用包装在 do catch 中即可正确处理错误。有关 Swifts 错误处理模型的详细信息,请参阅 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html。
至于要捕获哪个错误,只需浏览 Locksmith API,它就会抛出从 Keychain 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
}
}
}
我有一个网络服务 returns 我有一些数据,例如 name
、login
和 auth_token
。到目前为止,我在 NSUserDefaults 中保存了 name
和 login
。现在我也想安全地存储 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
class 有一个名为 response
的函数,还有一个属性 称为 response
(类型 NSHTTPURLResponse?
,看起来很熟悉 =))
在您的代码中调用 try
,这需要将封闭的 closure/function 标记为 throws
,或者您必须将代码包装在 do-catch
中
所以 swift 编译器所做的是推断您正在编写的闭包将 throws
作为其定义的一部分。这显然与应该传递给 func response
的闭包定义不匹配,因此它尝试 other response
它可以找到的 属性。然后它就完全失败了,因为你不能尝试 'call' 一个可选类型。
您应该在闭包中添加一个 do-catch 来处理 Locksmith 可能抛出的错误。
编辑:回应您的评论。您只需要将该调用包装在 do catch 中即可正确处理错误。有关 Swifts 错误处理模型的详细信息,请参阅 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html。
至于要捕获哪个错误,只需浏览 Locksmith API,它就会抛出从 Keychain 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
}
}
}