String 去掉这些可选值

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

使用Xcode 7测试版,Swift 2.0

我正在将凭证保存并加载到keychain,不知何故,当加载时,我得到了“可选(值)”返回,看起来这实际上是字符串的一部分,因为它在文本框中或发送到API时也会这样显示

这就是我现在保存和加载凭据的方式,正如您看到的,我做了很多额外的nil检查,以确保它不是nil或可选的,这确实是过度使用了解释标记

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中未发现该错误,