美文网首页iOS学习开发程序员
国外优秀教程精译 | Swift 可选值详解(上)

国外优秀教程精译 | Swift 可选值详解(上)

作者: 溪石iOS | 来源:发表于2019-03-26 21:58 被阅读30次

    英文原文

    Swift 是一门非常安全的语言,这里指的是 Swift 在防止代码意外崩溃方面做了很多努力。
    代码崩溃的一个常见原因是试图使用一个已损坏的或不存在的数据。举例来说,假设有一个方法:

    func getHaterStatus() -> String {
    return "Hate"
    }
    

    该方法没有任何参数,并且返回一个 string:“Hate”。然而有一天阳光明媚,这些心有怨恨的家伙们不感到怨恨了——会发生什么事?我们可能就不想返回任何东西了:毕竟这些人今天不怨恨了嘛。
    这时,一个空字符串也许是最好用来表明“没啥事”的,有时这也是事实。但是用数字如何表现“什么都没有”—— 用 0 表示“空数字”还是 -1 ?
    别急着定义你自己的表示规则,Swift 已经有了解决方案:可选值。可选值就是可能有值也可能没有值的变量。大多数人都觉得可选值很难理解,别担心——我将用各种方式来说明它,总有一种方式适合你。
    当使用 -> String 时,表示“这个方法会返回一个确定的 string ”,即表示该方法不会返回空值,因此它被称为安全的,因为你总是能获得一个值,这个值类型是 string 。反之,如果方法可能返回有值或空值,需要改写为下面这样:

    func getHaterStatus() -> String? {
        return "Hate"
    }
    

    注意这个额外的问号 String? 代表“可选的 string ”。当前的代码无论如何都会返回 “Hate”,让我们来修改一下:如果天气晴朗,怀恨者们将展开新的生活篇章,放弃他们仇恨的生活,因此返回空值。在 Swift 中,空值有特别的关键字: nil
    于是代码改为这样:

    func getHaterStatus(weather: String) -> String? {
        if weather == "sunny" {
            return nil
        } else {
            return "Hate"
        }
    }
    

    方法接受一个 string 参数(天气 weather )并返回一个 string (仇恨状态),但返回值可能有也可能没有——为 nil 。具体到本文例子中,就表示我们可能得到一个 string ,或者得到 nil 。
    那么重点来了:Swift 希望你的代码是真正安全的,使用 nil 就不是一个好主意。它会使你的代码崩溃,混淆你的代码逻辑,或者在界面上显示错误的内容。因此,当声明一个值为可选值之时,Swift 就要确保你能安全地处理它。
    试着把下面这行添加到你的 playground :

    var status: String
    status = getHaterStatus(weather: "rainy")
    

    第一行创建一个 string 型变量,第二行把 getHaterStatus()的返回值赋值给这个变量——参数表示今天下雨,这样可以保证仇恨者们正在仇恨中(返回值是"Hate”)。
    这段代码无法运行,因为我们声明的 String 型变量 status 要求一个值,但getHaterStatus()可能无法提供,因为它返回可选值。也就是说,我们表示 status 一定是个 string ,但实际上 getHaterStatus()可能啥也不返回。Swift 根本不会让你犯这个错误,这非常有用,因为它有效地阻止了一大堆常见错误。
    为了解决这个问题,我们需要把 status声明为 String?,或者干脆移除类型声明,让 Swift 自己推断类型。第一种方法如下:

    var status: String?
    status = getHaterStatus(weather: "rainy")
    

    第二种方式:

    var status = getHaterStatus(weather: "rainy")
    

    无论选择哪个,值都可能为空值,Swift 是不会让你冒险使用的。举例来说,假设有这么一个方法:

    func takeHaterAction(status: String) {
        if status == "Hate" {
            print("Hating")
        }
    }
    

    这段代码接受一个 string ,根据 string 内容打印一条消息。这个方法接受一个 String 值,却不是 String?——你无法传递一个可选值给它,它需要一个确切的值,导致无法把 status 变量传给它。
    Swift 有两个解决办法。两个都能用,但只能二选一。第一个解决方案是解包,它在条件语句中使用特定的语法规则。解包一次性做两件事情:检查可选值是否有值,如果有值就将其放入一个非可选值中并运行对应代码块。
    解包语法如下:

    if let unwrappedStatus = status {
        // unwrappedStatus 是非可选值
    } else {
        // 解包失败的处理
    }
    

    if let在一行代码中简洁地处理了检查和解包,这种方法非常常见。应用这种方法,我们能安全地把 getHaterStatus() 解包,并仅在非可选 string 有效存在时,才调用 takeHaterAction()
    这是完整代码:

    func getHaterStatus(weather: String) -> String? {
        if weather == "sunny" {
            return nil
        } else {
            return "Hate"
        }
    }
    
    func takeHaterAction(status: String) {
        if status == "Hate" {
            print("Hating")
        }
    }
    
    if let haterStatus = getHaterStatus(weather: "rainy") {
        takeHaterAction(status: haterStatus)
    }
    

    未完待续

    相关文章

      网友评论

        本文标题:国外优秀教程精译 | Swift 可选值详解(上)

        本文链接:https://www.haomeiwen.com/subject/tslovqtx.html