我正在按照this tutorial学习Swift for iOS 8 / OSX 10.10,并且多次使用术语“ unwrapped value ”,如本段(在Objects和Class下):
使用可选值时,您可以写吗?在诸如方法,属性和下标之类的操作之前 . 如果之前的值?是零,一切都在?被忽略,整个表达式的值为零 . 否则,可选值是解包,并且后面的一切都是?对未包装的 Value 采取行动 . 在这两种情况下,整个表达式的值都是可选值 .
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
我没有得到它,并在网上搜索没有运气 .
这意味着什么?
编辑
根据Cezary的回答,原始代码的输出与最终解决方案(在操场上测试)之间存在细微差别:
原始代码
Cezary的解决方案
在第二种情况下,超类的属性显示在输出中,而在第一种情况下有一个空对象 .
在这两种情况下,结果不应该相同吗?
Related Q&A : What is an optional value in Swift?
4 回答
首先,您必须了解可选类型是什么 . 可选类型基本上意味着变量可以是
nil
.例:
问号表示
canBeNil
可以nil
.这不起作用:
要从变量中获取值,如果它是可选的,则必须 unwrap it . 这只是意味着在最后加上感叹号 .
您的代码应如下所示:
旁注:
您还可以使用感叹号而不是问号声明选项以自动解包 .
例:
因此,修复代码的另一种方法是:
编辑:
您所看到的差异正是可选值为 wrapped 这一事实的症状 . 它上面还有另一层 . unwrapped 版本只显示直接对象,因为它是完全展开的 .
快速游乐场比较:
在第一种情况和第二种情况下,对象不会自动解包,因此您会看到两个"layers"(
{{...}}
),而在第三种情况下,您只看到一个图层({...}
),因为该对象正在自动解包 .第一种情况和后两种情况之间的区别在于,如果
optionalSquare
设置为nil
,则后两种情况将给出运行时错误 . 使用第一种情况中的语法,您可以执行以下操作:现有的正确答案很棒,但我发现,要让我完全理解这一点,我需要一个很好的类比,因为这是一个非常抽象和奇怪的概念 .
所以,除了正确答案之外,让我通过提供不同的视角来帮助那些“右脑”(视觉思维)开发人员 . 这是一个很好的比喻,对我帮助很大 .
Birthday Present Wrapping Analogy
将可选项视为像生日礼物一样,采用坚硬,坚硬,彩色的包装 .
在你打开礼物之前,你不要在包装内放任何东西 - 也许内部什么也没有!如果里面有东西,它可能是另一个存在,它也被包裹,也可能不包含任何内容 . 你甚至可能打开100个嵌套的礼物,最后发现除了包装之外什么都没有 .
如果Optional的值不是
nil
,那么现在您已经显示了一个包含内容的框 . 但是,特别是如果值没有明确地键入并且是变量而不是预定义的常量,那么您可能仍然需要先打开框,然后才能知道关于框中的内容的任何具体内容,例如它是什么类型,或者是什么实际 Value 是 .What's In The Box?! Analogy
即使你打开变量,你仍然像last scene in SE7EN中的布拉德皮特(警告:破坏者和非常R级的粗言秽语和暴力),因为即使在你打开礼物之后,你仍处于以下情况: you now have nil, or a box containing something (but you don't know what).
你可能知道某事的类型 . 例如,如果您将变量声明为类型
[Int:Any?]
,那么您就知道您有一个带有整数下标的(可能为空)Dictionary,它会生成任何旧类型的包装内容 .这就是为什么在Swift中处理集合类型(字典和数组)可能会变得多毛 .
例证:
'?'表示可选的链接表达式
'!'的意思是强制值
斯威夫特高度重视类型安全 . 整个Swift语言在设计时考虑了安全性 . 这是斯威夫特的标志之一,你应该张开双臂欢迎 . 它将有助于开发干净,可读的代码,并帮助防止应用程序崩溃 .
Swift中的所有选项都使用
?
符号划分 . 通过在您声明为可选类型的名称之后设置?
,您基本上将其转换为?
之前的类型,而是作为可选类型 .Using Optional
这确实 not 表示您正在使用
String
类型 . 这意味着您正在使用String?
(String Optional或Optional String)类型 . 事实上,每当你尝试在运行时,调试控制台将打印
Optional("foobar")
. “Optional()
" part indicates that this variable may or may not have a value at runtime, but just so happens to currently be containing the string " foobar ". This "Optional()
" indication will remain unless you do what is called " unwrapping”可选值 .Unwrapping 可选表示您现在将该类型转换为非可选类型 . 这将生成一个新类型,并将该可选内容中的值分配给新的非可选类型 . 这样您就可以对该变量执行操作,因为编译器已经保证它具有可靠的值 .
Conditionally Unwrapping 将检查可选项中的值是否为
nil
. 如果它不是nil
,则会有一个新创建的常量变量,该变量将被赋值并展开到非可选常量中 . 从那里你可以安全地使用if
块中的非可选项 .有条件地展开选项是访问可选值的最简洁方法,因为如果它包含nil值,那么if let块中的所有内容都不会执行 . 当然,与任何if语句一样,您可以包含else块
Forcibly Unwrapping 是通过使用所谓的
!
("bang")运算符完成的 . 这不太安全,但仍然允许您的代码编译 . 但是,无论何时使用bang运算符,在强行展开之前,必须确保变量确实包含一个实数值 .以上是完全有效的Swift代码 . 它打印出
myString
的值,该值设置为"foobar" . 用户将在控制台中看到foobar
并且's about it. But let'假设从未设置过该值:现在我们手上有不同的情况 . 与Objective-C不同,只要尝试强制解包可选项,并且未设置可选项且
nil
,当您尝试打开可选项以查看应用程序中的内容将崩溃时 .Unwrapping w/ Type Casting . 正如我们之前所说的那样,当你是
unwrapping
可选实际上你正在转换为非可选类型时,你也可以将非可选类型转换为其他类型 . 例如:在我们的代码中的某个地方,变量
something
将设置一些值 . 也许我们正在使用泛型,或者可能还有一些其他逻辑会导致这种情况发生变化 . 所以稍后在我们的代码中我们想要使用something
但是如果它是不同的类型仍然能够区别对待它 . 在这种情况下,您将需要使用as
关键字来确定:注意两个
as
关键字之间的区别 . 就像之前我们强行打开一个可选项一样,我们使用!
bang运算符来执行此操作 . 在这里你将做同样的事情,但不是像只是一个非可选的铸造,你也将它作为Int
. 并且它必须能够被转发为Int
,否则,就像使用bang运算符一样,当值为nil
时,您的应用程序将崩溃 .并且为了在某种类型或数学运算中使用这些变量,必须将它们解包以便这样做 .
例如,在Swift中,只有相同种类的有效数字数据类型可以相互操作 . 当您使用
as!
转换类型时,您正在强制转换该变量,就好像它是 certain 那样,因此可以安全地操作并且不会使应用程序崩溃 . 只要变量确实属于你所使用的类型,这是可以的,否则你手上就会弄得一团糟 .尽管如此,使用
as!
进行转换将允许您的代码进行编译 . 通过铸造as?
是一个不同的故事 . 实际上,as?
将Int
声明为完全不同的数据类型 .Now it is Optional(0)
如果你曾经尝试写过类似的东西
你的数学老师可能会给你一个"F" . 与Swift相同 . 除了Swift之外,根本不会编译,而不是给你一个分数 . Because at the end of the day the optional may in fact be nil .
安全第一孩子 .