String 去掉这些可选值
使用Xcode 7测试版,Swift 2.0 我正在将凭证保存并加载到keychain,不知何故,当加载时,我得到了“可选(值)”返回,看起来这实际上是字符串的一部分,因为它在文本框中或发送到API时也会这样显示 这就是我现在保存和加载凭据的方式,正如您看到的,我做了很多额外的nil检查,以确保它不是nil或可选的,这确实是过度使用了解释标记String 去掉这些可选值,string,swift,nsstring,optional,swift2,String,Swift,Nsstring,Optional,Swift2,使用Xcode 7测试版,Swift 2.0 我正在将凭证保存并加载到keychain,不知何故,当加载时,我得到了“可选(值)”返回,看起来这实际上是字符串的一部分,因为它在文本框中或发送到API时也会这样显示 这就是我现在保存和加载凭据的方式,正如您看到的,我做了很多额外的nil检查,以确保它不是nil或可选的,这确实是过度使用了解释标记 func SaveCredentials(credentials : [String : String!]!) -> Bool { if(c
func SaveCredentials(credentials : [String : String!]!) -> Bool
{
if(credentials.count == 2)
{
//only proceed when we have two keys: username and password
let username = credentials["username"]
let password = credentials["password"]
if let usernameStr = username
{//also tried username!=nil && password != nil
if let passwordStr = password
{ //usernameStr and passwordStr is of type String!
let NsDataUsername = usernameStr!.dataUsingEncoding(NSUTF8StringEncoding)
let NsDataPassword = passwordStr!.dataUsingEncoding(NSUTF8StringEncoding)
if(NsDataUsername != nil && NsDataPassword != nil)
{
LocalStorage.saveToKeyChain("username", data: NsDataUsername!)
LocalStorage.saveToKeyChain("password", data: NsDataPassword!)
return true
}
}
}
}
return false
}
func LoadCredentials() -> [String : String!]?
{
let NsDataUsername = LocalStorage.loadFromKeyChain("username")
let NsDataPassword = LocalStorage.loadFromKeyChain("password")
if(NsDataUsername != nil && NsDataPassword != nil)
{
let username : String! = String(NSString(data: NsDataUsername!, encoding: NSUTF8StringEncoding))
let password : String! = String(NSString(data: NsDataPassword!, encoding: NSUTF8StringEncoding))
if let usernameStr = username
{
if let passwordStr = password
{ // password is of type String!, passwordStr is of type String
var credentials : [String: String!] = [String : String]()
credentials["username"] = usernameStr
credentials["password"] = passwordStr
return credentials
}
}
}
return nil
}
当我发送到Api时,这是我的方法,它也需要一个非可选字符串。此方法在登录、从文本字段获取字符串时确实有效,但在从keychain获取字符串时不会过滤掉可选内容
func LoginUser(email : String!, password : String!)
{
print("LoginUser(email : \(email), password: \(password))")
var parameters = [String : AnyObject]()
parameters["UserName"] = email
parameters["Password"] = password
......
我发送到SaveCredentials方法的字符串与用户登录时使用的字符串相同:
func LoginLocalAccount(email : String!, password : String!)
{
databaseAPI.LoginUser(email!, password: password!) //login goes just fine
saveCredentials(email!, password: password!) //manages to get Optional in it..
}
我怀疑它与保存和从keychain加载有关,因为兴趣是我用来保存和从keychain加载的
func LoginUser(email : String!, password : String!)
{
print("LoginUser(email : \(email), password: \(password))")
var parameters = [String : AnyObject]()
parameters["UserName"] = email
parameters["Password"] = password
......
我想摆脱它们,因为当应用程序启动时,它会加载凭据并尝试在我的API上登录。当然,我得到一个错误,用户名不是有效的电子邮件,因为它是可选的(email@adress.com)您过度使用了
代码>。你不需要它们。尝试了解更多关于隐式展开的可选项、可选项。。。你的代码乱七八糟(无意冒犯,大家都在学习)
回到您的可选问题,它是由以下行引起的:
let username : String! = String(NSString(data: NsDataUsername!, encoding: NSUTF8StringEncoding))
convency init?(数据:NSData,编码:UInt)
-内部部分使用可失败的初始值设定项,因此,NSString?
是结果。然后用可选的NSString?
初始化String
,也会生成可选的。但是,这样做毫无意义
第一部分-删除可选部分
使用新的防护装置
:
guard let loadedPassword = NSString(data: passwordData, encoding: NSUTF8StringEncoding) else {
fatalError("Ooops")
}
loadedPassword
现在包含NSString
(不是NSString?
)
第二部分-NSString
->String
你可能读过(如果没有,读过)关于桥接。。。如果您可以与String
自由交换NSString
,您可以认为您完成了:
var dict = [String:String]()
dict["password"] = loadedPassword
var dict = [String:String]()
dict["password"] = loadedPassword as String
没有。它会产生以下错误:
NSString
不能隐式转换为String
;你是故意的吗
是否使用“as”显式转换
稍微改变一下,现在您就完成了:
var dict = [String:String]()
dict["password"] = loadedPassword
var dict = [String:String]()
dict["password"] = loadedPassword as String
完整示例
let password = "Hallo"
guard let passwordData = password.dataUsingEncoding(NSUTF8StringEncoding) else {
fatalError("Ooops")
}
// save/load to/from keychain
guard let loadedPassword = NSString(data: passwordData, encoding: NSUTF8StringEncoding) else {
fatalError("Ooops")
}
var dict = [String:String]()
dict["password"] = loadedPassword as String
print(dict) // "[password: Hallo]\n"
首先,这些不是非选择性的。它们是隐式展开的可选项(这些可选项可以是nil
)。第二,只是因为可选(email@address.com)
使用print
函数打印并不意味着它会显示在其他任何地方。但这就是问题所在,它确实会显示,即使我再次在文本框中显示它们,它也会显示可选值,然后这是字符串中的实际值。是的,我注意到了,所以我的猜测是,如果在保存时出现问题,您是否有可能查看一下我的代码,看看我做错了什么?第一步是消除所有错误!。您不需要它们中的任何一个—隐式可选类型(可能是非可选的,或者可能是?
)和强制展开。通读一遍,了解选项以及如何处理它们,然后重写代码,去掉的每个实例代码>。一旦你这样做了,你应该对问题所在有更好的理解。嗨,罗伯特,非常感谢你,我只是在优化我的代码,在保存之前和加载之后也开始使用guard。这确实是过度使用了!,根本没有生产代码,只是想知道哪里出了问题。但在NSString中未发现该错误,