What is an “unwrapped value” in Swift?
我正在按照本教程学习iOS 8/OSX 10.10的Swift,并多次使用术语"展开值",如本段(在"对象和类"下)所示:
When working with optional values, you can write ? before operations
like methods, properties, and subscripting. If the value before the ?
is nil, everything after the ? is ignored and the value of the whole
expression is nil. Otherwise, the optional value is unwrapped, and
everything after the ? acts on the unwrapped value. In both cases, the
value of the whole expression is an optional value.
1 2 | let optionalSquare: Square? = Square(sideLength: 2.5, name:"optional square") let sideLength = optionalSquare?.sideLength |
我不明白,没有运气就在网上搜索。
这意味着什么?
编辑从Cezary的答案来看,原始代码的输出与最终解决方案(在操场上测试)之间存在细微差异:
原始代码Cezary的解决方案在第二种情况下,超类的属性显示在输出中,而在第一种情况下有一个空对象。
在这两种情况下,结果不应该相同吗?
相关问答:Swift中的可选值是什么?
首先,您必须了解可选类型是什么。可选类型基本上意味着变量可以是
例子:
1 2 | var canBeNil : Int? = 4 canBeNil = nil |
问号表示
这不起作用:
1 2 | var cantBeNil : Int = 4 cantBeNil = nil // can't do this |
如果变量是可选的,则要从变量中获取值,必须将其展开。这只意味着在结尾加一个感叹号。
1 2 | var canBeNil : Int? = 4 println(canBeNil!) |
您的代码应该如下所示:
1 2 | let optionalSquare: Square? = Square(sideLength: 2.5, name:"optional square") let sideLength = optionalSquare!.sideLength |
旁白:
还可以声明选项,通过使用感叹号而不是问号自动展开。
例子:
1 2 | var canBeNil : Int! = 4 print(canBeNil) // no unwrapping needed |
所以修复代码的另一种方法是:
1 2 | let optionalSquare: Square! = Square(sideLength: 2.5, name:"optional square") let sideLength = optionalSquare.sideLength |
编辑:
您看到的差异正是包装可选值这一事实的症状。上面还有一层。展开版本只显示直线对象,因为它是展开的。
一个快速的操场比较:
在第一和第二种情况下,对象不会自动展开,因此您会看到两个"层"(
第一种情况和第二种情况的区别在于,如果将
1 2 3 4 5 | if let sideLength = optionalSquare?.sideLength { println("sideLength is not nil") } else { println("sidelength is nil") } |
现有的正确答案很好,但我发现要完全理解这一点,我需要一个很好的类比,因为这是一个非常抽象和奇怪的概念。
所以,让我来帮助那些"右脑"(视觉思维)开发者,除了给出正确的答案外,还提供不同的视角。这是一个很好的类比,对我有很大帮助。
生日礼物包装类比
把可选方案想象成像生日礼物一样,用硬的、硬的、彩色的包装。
在打开礼物之前,你不知道包装里有没有什么东西——也许里面什么都没有!如果里面有什么东西,它可能是另一个礼物,也被包裹着,也可能不包含任何东西。你甚至可以打开100个嵌套的礼物,最终发现只有包装。
如果选项的值不是
盒子里有什么?类推!
即使你打开了变量,你仍然像布拉德皮特在SE7en的最后一幕(警告:剧透和非常R级的脏话和暴力),因为即使你打开了现在,你也处于以下情况:你现在有
你们可能知道什么东西的类型。例如,如果您将变量声明为类型
这就是为什么在swift中处理集合类型(字典和数组)会有点麻烦。
例证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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) |
斯威夫特高度重视类型安全。整个Swift语言的设计都考虑到了安全性。它是斯威夫特的标志之一,你应该张开双臂欢迎它。它将帮助开发干净、可读的代码,并帮助防止应用程序崩溃。好的。
Swift中的所有期权都用
Note: A variable or type
Int is not the same asInt? . They are two different types that can not be operated on each other.Ok.
使用可选好的。
1 2 3 | var myString: String? myString ="foobar" |
这并不意味着您正在使用的是
1 | print(myString) |
运行时,调试控制台将打印
展开一个可选项意味着您现在将该类型强制转换为非可选类型。这将生成一个新类型,并将该可选类型中的值赋给新的非可选类型。通过这种方式,您可以对该变量执行操作,因为编译器保证该变量具有实值。好的。
有条件地展开将检查选项中的值是否为
Note: You can give your conditionally unwrapped constant the same name as the optional variable you are unwrapping.
Ok.
1 2 3 4 | if let myString = myString { print(myString) // will print"foobar" } |
有条件地展开选项是访问选项值的最干净的方法,因为如果它包含一个nil值,那么if let块中的所有内容都不会执行。当然,像任何if语句一样,您可以包含一个else块好的。
1 2 3 4 5 6 7 | if let myString = myString { print(myString) // will print"foobar" } else { print("No value") } |
强行展开是通过使用被称为
1 2 3 4 5 | var myString: String? myString ="foobar" print(myString!) |
上述代码完全有效。它打印出设定为"foobar"的
1 2 3 | var myString: String? print(myString!) |
现在我们有了不同的情况。与Objective-C不同的是,每当试图强制展开某个选项时,如果该选项尚未设置且为
拆封w/型铸造。正如我们前面所说,当您是
1 | var something: Any? |
在我们的代码中的某个地方,变量
Note: The
as operator is how you type cast in Swift.Ok.
1 2 3 4 5 6 7 8 9 10 11 12 | // Conditionally if let thing = something as? Int { print(thing) // 0 } // Optionally let thing = something as? Int print(thing) // Optional(0) // Forcibly let thing = something as! Int print(thing) // 0, if no exception is raised |
注意两个
为了在某种排序或数学运算中使用这些变量,它们必须被展开才能做到这一点。好的。
例如,在swift中,只能对相同类型的有效数字数据类型进行操作。当您使用
尽管如此,使用
现在是
如果你曾经试着写作业好的。
1 | 1 + Optional(1) = 2 |
你的数学老师可能会给你一个"F"。斯威夫特也一样。但斯威夫特宁愿不编译也不愿给你一个分数。因为在一天结束的时候,这个选项实际上可能是零。好的。
安全第一的孩子。好的。好啊。
"?"表示可选链接表达式"!"手段就是力量值