包含数组的字典 - 为什么需要解包?

时间:2016-01-02 02:22:47

标签: swift dictionary

我试图解决为什么当涉及到Swift中包含数组的字典时,感觉直观是非法的。

假设我有:

 var arr = [1,2,3,4,5]
 var dict = ["a":1, "b":2, "test":arr]

我可以像这样轻松访问字典成员:

 dict["a"]
 dict["b"]
 dict["test"]

正如预期的那样,每个都将返回存储的值,包括键的数组" test":

  

[1,2,3,4,5]

我对此基于其他语言的直观反应是,这应该是合法的:

 dict["test"][2]

我期望返回3。当然,这在Swift中不起作用。经过大量的修补后,我意识到这是正确的方法:

 dict["test"]!.objectAtIndex(2)

意识到这一点,我回到我直观的方法并说,"那么,这也应该有效:"

 dict["test"]![2]

它做了什么......我真正得到的是为什么解包没有解开暗示的原因。我对Swift"思考的方式缺少什么?"

3 个答案:

答案 0 :(得分:4)

Swift中的所有字典查找返回可选变量。

为什么呢?因为您正在查找的密钥可能不存在。如果密钥不存在,则字典返回nil。由于可以返回nil,因此查找类型必须是可选

因为字典查找返回 Optional 值,所以必须将其解包。这可以通过各种方式完成。处理此问题的一种安全方法是使用可选链接并结合可选绑定

if let value = dict["test"]?[2] {
    print(value)
}

在这种情况下,如果"test"不是有效密钥,则整个 dict["test"]?[2]将返回nil可选绑定 if let将失败,因此print永远不会发生。

如果您强行打开字典访问权限,那么如果密钥不存在则会崩溃:

dict["test"]![2] // this will crash if "test" is not a valid key

答案 1 :(得分:1)

在Objective-C世界中,如果您尝试3访问dict[@"test"][2],则可能会崩溃。如果dict[@"test"]为零或从dict[@"test"]获得的数组仅包含两个元素,该怎么办?当然,您已经知道数据就是这样。然后,它完全没有问题。

如果从后端获取数据并且它有一些问题怎么办?这仍将通过编译器,但应用程序在运行时崩溃。用户不是程序员,他们只知道:应用程序崩溃。可能他们不想再使用它了。所以,底线是:根本没有崩溃。

Swift引入了一个名为Optional Type的类型,这意味着可能缺少值,因此代码在运行时是安全的。在Swift内部,它实际上是在尝试实现if-else来检查数据是否缺失。

对于您的情况,我将分开两部分:

第1部分dict["test"]!告诉编译器忽略if-else语句并返回值,无论如何。相反,如果值丢失,dict["test"]?将返回nil。术语是显式展开

第2部分dict["test"]?[2]可能会发生崩溃。如果dict["test"]?返回一个有效数组且它只有两个元素怎么办?使用Objective-C中的dict[@"test"][2],这种存储数据的方式是相同的。这就是为什么它有一个叫做可选类型展开的东西。只有当有效数据存在时,它才会进入if分支。最安全的方式:

if let element = dict["test"]?[2] {
    // do your stuff
}

答案 2 :(得分:1)

问题是Dictionary基于密钥的下标返回一个可选项 - 因为密钥可能不存在。

实现目标的最简单方法是通过可选链接。这编译:

dict["test"]?[2]

但请注意,结果仍然是可选的(即,如果没有键test,那么您可以返回nil并且不会运行第二个下标。因此,您可能仍需要稍后打开它。但它与!的不同之处在于,如果该值不存在,您的程序将不会崩溃,而只是评估nil的可选结果。

请参阅here以获取处理期权的一长串方法,或here了解更多关于期权的背景信息。