可选类中的可选属性VS可选字典中的可选值

时间:2016-01-07 22:06:34

标签: ios swift swift2

在尝试访问可选类VS中的可选属性值时,我注意到了一些有趣的行为VS试图访问可选dictionaires中可选值的值。

似乎在前一种情况下,您只需要打开一次即可访问该值。但是,在后一种情况下,您必须解开两次才能访问该值。我想知道为什么会这样,并且希望有人能为我提供一些见解!

下面是访问可选类

中可选属性值的示例
class Cat{
    var food : Food?
}

class Food{
     var amount : Int?
}

var meowzer = Cat()
meowzer.food = Food()
meowzer.food?.amount = 10
var catFoodAmt = meowzer.food?.amount

print("\(catFoodAmt)")

if let catFoodCount = meowzer.food?.amount{
    print("\(catFoodCount)")
}

第一个印刷声明的结果是:

Optional(10)

第二个打印语句(解包后)的结果是:

10

以下是访问可选字典中可选值的值的示例

var dog : [String : Int?]?
dog = ["treat_count" : 10]

var dogTreatAmt = dog?["treat_count"]

print("\(dogTreatAmt)")

if let dogTreatCount = dog?["treat_count"] , dogTreatCountFinal = dogTreatCount{

    print("\(dogTreatCount)")
    print("\(dogTreatCountFinal)")

}

第一个印刷声明的结果是:

Optional(Optional(10))

第二个打印语句的结果(在解缠一次之后)是:

Optional(10)

第三个印刷语句的结果(在展开两次之后)是:

10

为什么我需要解开两次以在第二种情况下访问所需的值而不是第一种情况?

我的猜测是,如果我使用的是#34; treat_count" (例如" count"例如)然后该键的值将为零。但是,我还没能找到一个iOS"规则"或者更好地解释为什么会这样。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

区别在于Cat.food?.amount返回Int?Dictionary<String, Int?>.subscript(String)返回Int??

这是因为Dictionary.subscript<Key>返回Element?Element这里是Int?。因此,您将获得一个额外级别的Optional。

可选链接只是删除了一个额外的可选包装。它不会崩溃所有Optionals。在一种情况下,你有两个,折叠为1(一个?),第二个你有三个,折叠为2(一个?)。

正如vadian所说,这将是一个疯狂的词典,所以它不太可能出现在好的Swift中,但它可以被推理出来。如果不是这样,你就会失去信息。

答案 1 :(得分:0)

它实际上是有意义的:只计算?s的数量:)。

在第一个示例中,该属性是可选的,在第二个示例中,您有一个可选字典,其中键是字符串,值是可选整数。

因此,如果要访问第二个示例的值,则必须打开字典,然后解开该字典中针对给定键的任何内容。

答案 2 :(得分:0)

这是一个很好的问题。让我们来看一下词典的类型定义:

struct Dictionary<Key : Hashable, Value>

下标函数的签名:

public subscript (key: Key) -> Value?

这也可以被认为是:

public subscript (key: Key) -> Optional<Value>

有了这个,让我们看看你的字典,输入为:

Dictionary<String, Int?>

或者更明确地

Dictionary<String, Optional<Int>>

其中Value的类型为Optional<Int>,而Key的类型为String

因此,如果我们在密钥中替换,则下标定义为:

subscript (key: String) -> Optional<Value>

如果我们在Value中替换它,我们就会得到你所看到的:

subscript (key: String) -> Optional<Optional<Int>

现在,让我们分解您的代码并使所有内容融合在一起:

var dogTreatAmt = dog?["treat_count"]

由于dog是可选的,无论您调用什么,结果也会包含在Optional中,我们会暂时将其视为Optional(FunctionReturn)

现在让我们看看FunctionReturn,它是下标函数。我们已经确定这将返回Optional<Optional<Int>>

这意味着你真的要回归Optional<Optional<Optional<Int>>>,但正如Rob Napier所说, &#34;可选链接会删除额外的可选包装,使用它&#34;。