为了账号安全,请及时绑定邮箱和手机立即绑定

在Swift中什么是“未包装的值”?

在Swift中什么是“未包装的值”?

月关宝盒 2019-10-05 14:07:04
通过遵循本教程,我正在学习iOS 8 / OSX 10.10的Swift ,并且多次使用术语“ 未包装的值 ”,如本段中(在Objects和Class下):使用可选值时,您可以编写?在方法,属性和下标之类的操作之前。如果前值?是零,之后的所有内容?将被忽略,整个表达式的值为nil。否则,将取消包装可选值,以及?之后的所有内容。作用于未包装的值。在这两种情况下,整个表达式的值都是一个可选值。let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") let sideLength = optionalSquare?.sideLength我不明白,在网上没有运气。这是什么意思?编辑根据Cezary的回答,原始代码的输出与最终解决方案(在操场上测试)的输出之间存在细微差别:原始码塞扎里的解决方案在第二种情况下,超类的属性显示在输出中,而在第一种情况下,则显示一个空对象。两种情况下的结果难道不应该相同吗?
查看完整描述

3 回答

?
绝地无双

TA贡献1946条经验 获得超4个赞

首先,您必须了解什么是Optional类型。可选类型基本上意味着变量可以是 nil。


例:


var canBeNil : Int? = 4

canBeNil = nil

问号表明一个事实,即canBeNil可以nil。


这将不起作用:


var cantBeNil : Int = 4

cantBeNil = nil // can't do this

要从变量中获取值(如果该值是可选的),则必须将其解包。这仅意味着在结尾处添加一个感叹号。


var canBeNil : Int? = 4

println(canBeNil!)

您的代码应如下所示:


let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") 

let sideLength = optionalSquare!.sideLength

旁注:


您还可以声明可选内容,以使用感叹号而不是问号来自动展开。


例:


var canBeNil : Int! = 4

print(canBeNil) // no unwrapping needed

因此,修复代码的另一种方法是:


let optionalSquare: Square! = Square(sideLength: 2.5, name: "optional square") 

let sideLength = optionalSquare.sideLength

编辑:

您所看到的区别恰好是可选值被包装的症状。在其之上还有另一层。在展开的版本只是表明直对象,因为它是很好,解开。


快速游乐场比较:


//img1.sycdn.imooc.com//5d9833360001c9d513160232.jpg

在第一种和第二种情况下,对象不会自动解包,因此您会看到两个“图层”({{...}}),而在第三种情况下,您会看到仅一层({...}),因为对象已被自动解包。


第一种情况与第二种情况之间的区别在于,如果optionalSquare将设置为,则后两种情况会给您带来运行时错误nil。在第一种情况下使用语法,您可以执行以下操作:


if let sideLength = optionalSquare?.sideLength {

    println("sideLength is not nil")

} else {

    println("sidelength is nil")

}


查看完整回答
反对 回复 2019-10-05
?
婷婷同学_

TA贡献1844条经验 获得超8个赞

现有的正确答案很好,但是我发现对于我来说,要完全理解这一点,我需要一个很好的类比,因为这是一个非常抽象和怪异的概念。


因此,让我通过提供正确答案之外的其他观点来帮助那些“头脑敏捷”(视觉思维)开发人员。这是一个很好的类比,对我很有帮助。


生日礼物包装类比


可以将可选商品视为生日礼物,以硬,硬,彩色的包装包裹。


在打开礼物之前,不知道包裹内是否有东西-也许里面什么都没有!如果里面有东西,那可能是另一个礼物,也被包裹了,也可能什么也没有。您甚至可以拆开100个嵌套的礼物,最后发现除了包裹外别无其他。


如果option的值不是nil,那么您已经显示了一个包含某些内容的框。但是,尤其是如果该值未明确键入并且是变量而不是预定义常量,那么您可能仍需要打开该框,然后才能知道该框中内容的具体信息,例如其类型或类型。实际值是。


盒子里装了什么?!比喻


即使在解开变量之后,您仍然像SE7EN的最后一幕中的布拉德·皮特(Brad Pitt)(警告:破坏者和非常R级的粗言秽语和暴力),因为即使在解开当前之后,您仍处于以下情况:您现在有了nil,或一个装有某些物品的盒子(但您不知道是什么)。


您可能知道某物的类型。例如,如果您将变量声明为type,[Int:Any?]那么您将知道您有一个(可能为空)Dictionary,该字典具有整数下标,该整数下标会产生任何旧类型的包装内容。


这就是为什么在Swift中处理集合类型(字典和数组)会有点麻烦。


例子:


typealias presentType = [Int:Any?]


func wrap(i:Int, gift:Any?) -> presentType? {

    if(i != 0) {

        let box : presentType = [i:wrap(i-1,gift:gift)]

        return box

    }

    else {

        let box = [i:gift]

        return box

    }

}


func getGift() -> String? {

    return "foobar"

}


let f00 = wrap(10,gift:getGift())


//Now we have to unwrap f00, unwrap its entry, then force cast it into the type we hope it is, and then repeat this in nested fashion until we get to the final value.


var b4r = (((((((((((f00![10]! as! [Int:Any?])[9]! as! [Int:Any?])[8]! as! [Int:Any?])[7]! as! [Int:Any?])[6]! as! [Int:Any?])[5]! as! [Int:Any?])[4]! as! [Int:Any?])[3]! as! [Int:Any?])[2]! as! [Int:Any?])[1]! as! [Int:Any?])[0])


//Now we have to DOUBLE UNWRAP the final value (because, remember, getGift returns an optional) AND force cast it to the type we hope it is


let asdf : String = b4r!! as! String


print(asdf)


查看完整回答
反对 回复 2019-10-05
  • 3 回答
  • 0 关注
  • 547 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信