Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何安全退回超出其范围的未包装的可选产品?_Swift - Fatal编程技术网

Swift 如何安全退回超出其范围的未包装的可选产品?

Swift 如何安全退回超出其范围的未包装的可选产品?,swift,Swift,我是个笨蛋,请容忍我: func createEmployeeCode() -> String? { let email = UserDefaults.standard.object(forKey: "email_Saved") as? String let employeeCode = UserDefaults.standard.object(forKey: "employeeCode_Saved") as? String if let emailString = em

我是个笨蛋,请容忍我:

func createEmployeeCode() -> String? {
    let email = UserDefaults.standard.object(forKey: "email_Saved") as? String
    let employeeCode = UserDefaults.standard.object(forKey: "employeeCode_Saved") as? String

if let emailString = email,
    let employeeCodeString = employeeCode {
    return (emailString+employeeCodeString)
}

return (emailString+employeeCodeString) //ERROR: Use of unresolved identifier 'employeeCodeString' & Use of unresolved identifier 'emailString'
}
我理解错误显示的原因是因为我试图在这里返回不同范围内的内容,但如何让函数在没有“可选[…]”标记的情况下同时返回两个字符串?

(旁注:使用
UserDefaults.standard.string(forKey:)

问题是,你不知道这些字符串是否同时存在——如果它们存在,你已经有了一个很好的
if let
返回你的答案。现在的问题是,如果一个或两个都是
nil
,您想做什么?也许您希望从整个函数返回
nil
。如果是,

func createEmployeeCode() -> String? {
    let email = UserDefaults.standard.string(forKey: "email_Saved")
    let employeeCode = UserDefaults.standard.string(forKey: "employeeCode_Saved")

    if let emailString = email,
        let employeeCodeString = employeeCode {
        return (emailString+employeeCodeString) //successful unwrapping, let's concatenate!
    }

    return nil //if one or both `if let`s fail, we end up here
}
当然,在这种“坏”情况下,你可以随心所欲。也许你想展示你所有的弦。在这种情况下:

func createEmployeeCode() -> String {
    let email = UserDefaults.standard.string(forKey: "email_Saved")
    let employeeCode = UserDefaults.standard.string(forKey: "employeeCode_Saved")

    return (email ?? "") + (employeeCode ?? "") //this works in the "good" case, too, and uses the nil coalescing operator `??`
}
在本例中,您可以看到返回值不再是可选的。这是因为即使两个字符串都不存在,它也会连接两个空字符串。如果感觉不舒服,您可以保留可选的返回值,并在返回前进行快速检查:

if email == nil && employeeCode == nil { return nil }

当从
userDefaults
返回值时,您试图将其作为
对象而不是
string

func createEmployeeCode() -> String? {
    let email:String = UserDefaults.standard.string(forKey: "email_Saved") ?? ""
    let employeeCode:String = UserDefaults.standard.string(forKey: "employeeCode_Saved") ?? ""

    let emailString = "\(email)\(employeeCode)"

    return emialString
}

根据你想要达到的目标,有不同的方法来解决这个问题


如果您始终希望创建
员工代码
(即使代码为空):

  • 尝试使用“
    nil
    合并运算符”。
  • func createEmployeeCode()->字符串{
    让email=UserDefaults.standard.object(forKey:“email\u已保存”)作为?字符串??“
    让employeeCode=UserDefaults.standard.object(forKey:“employeeCode\u已保存”)作为?字符串??“
    返回(电子邮件+员工代码)
    }
    
    要解释这里发生的事情:

  • 我们正在展开
    电子邮件
    ,如果找不到
    电子邮件
    ,则默认值为空字符串,
    “”
  • 我们对
    employeeCode
    也采取同样的做法
  • 虽然这不是一种解决所有未包装问题的方法,但它适合您的
    电子邮件
    员工代码
    ,因为您总是希望根据原始问题返回一些内容。我还将返回类型更改为非可选


    如果员工代码必须始终包含一封
    电子邮件
    以及一封
    代码
    ,那么如果找不到其中一封,我们希望返回
    nil

  • 尝试使用
    guard
    语句。guard语句非常适合验证,可读性非常强:
  • func createEmployeeCode()->字符串?{
    guard let email=UserDefaults.standard.object(forKey:“email_已保存”)为?字符串else{return nil}
    guard让employeeCode=UserDefaults.standard.object(forKey:“employeeCode_已保存”)作为?字符串else{return nil}
    返回(电子邮件+员工代码)
    }
    
    以下是我希望在普通生产应用程序中实现的方法

    (在普通的生产应用程序中,你不会这么做!但这就是你要寻找的“习惯用语”)

    请注意,返回在很大程度上是没有意义的-在有问题的应用程序中,如果其中一个守卫打破了,你就“完蛋了”。我可能只会返回一个空白字符串(或者更可能是“name\u error”之类的内容),因为此时应用程序架构已经彻底崩溃了。

    尝试以下功能:

    func createEmployeeCode() -> String {
        let email = UserDefaults.standard.object(forKey: "email_Saved") as? String
        let employeeCode = UserDefaults.standard.object(forKey: "employeeCode_Saved") as? String
        return [email, employeeCode].compactMap { $0 }.joined(separator: "")
    }
    

    如果其中一个为零或两者都存在,它将返回email或employeeCode或email+employeeCode;如果两者都漏掉,它将返回空字符串

    确切的错误是什么?NewCoder,你真正要找的是“守卫”-见答案。这就是您在这里使用的“惯用语”。您不应该只使用
    来消除错误。当然,编译器没有抱怨,但是现在您可以
    createEmployeeCode()
    并返回
    ,这显然是没有意义的。我建议不要在函数中添加后缀
    (如果可能的话)
    ,除非函数在静默状态下失败。基于他们的反馈,开发人员应该很清楚这一点IDE@Chackle是的,这是一个有趣的问题。我在“代码应该是自文档化的”阵营,也就是“长得离谱的变量名”阵营。这类事情需要讨论。干杯
    func createCodeIfPossible() -> String? {
    
     guard let e = UserDefaults.standard.object(forKey: "email_Saved") else {
        print("serious problem, there's no email saved")
        // at this point the app is completely buggered, so give up
        return ""
     }
    
     guard let c = UserDefaults.standard.object(forKey: "employeeCode_Saved") else {
        print("serious problem, there's no code saved")
        // at this point the app is completely buggered, so give up
        return ""
     }
    
     return e + c
    } 
    
    func createEmployeeCode() -> String {
        let email = UserDefaults.standard.object(forKey: "email_Saved") as? String
        let employeeCode = UserDefaults.standard.object(forKey: "employeeCode_Saved") as? String
        return [email, employeeCode].compactMap { $0 }.joined(separator: "")
    }