【问题标题】:Optional properties in optional classes VS Optional values in optional dictionaries可选类中的可选属性 VS 可选字典中的可选值
【发布时间】:2016-01-07 22:06:34
【问题描述】:

在尝试访问可选类中的可选属性的值时,我注意到一些有趣的行为,而尝试访问可选字典中的可选值的值。

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

以下是访问可选类中可选属性值的示例

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

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

我的猜测是,如果我使用“treat_count”以外的键(例如“count”),那么该键的值将为零。但是,我无法找到 iOS“规则”或更好的解释为什么会这样。任何帮助将不胜感激。

【问题讨论】:

  • [String : Int?] 是理论上的,实际上字典中的任何键和值都不能是nil

标签: ios swift swift2


【解决方案1】:

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

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

可选链接只是在使用它的时候删除了一个额外的可选包装。它不会折叠所有选项。在一种情况下,您有两个,折叠到 1(对于一个 ?),在第二种情况下,您有三个,折叠到 2(对于一个 ?)。

正如 vadian 所暗示的,这将是一个疯狂的字典,所以它不太可能出现在好的 Swift 中,但它可以被推理。如果不是这样,您将丢失信息。

【讨论】:

  • 嗯!我不知道 Dictionary.subscripty 返回了 Element?另外,感谢您提供有关可选链接的额外信息!
【解决方案2】:

这实际上是有道理的:只需计算 ?s 的数量 :)。

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

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

【讨论】:

    【解决方案3】:

    这是个好问题。让我们考虑一下 Dictionary 的类型定义:

    struct Dictionary<Key : Hashable, Value>
    

    以及下标函数的签名:

    public subscript (key: Key) -> Value?
    

    也可以认为是:

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

    有了这个,让我们看看你的字典,它的类型是:

    Dictionary<String, Int?>
    

    或者更明确

    Dictionary<String, Optional<Int>>
    

    其中ValueOptional&lt;Int&gt; 类型,KeyString 类型

    所以如果我们代入键,下标定义为:

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

    如果我们将其替换为 Value,我们会得到您所看到的:

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

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

    var dogTreatAmt = dog?["treat_count"]
    

    由于dog是可选的,所以不管你怎么调用它,结果也会被包裹在一个Optional中,我们暂时认为是Optional(FunctionReturn)

    现在我们来看看FunctionReturn,它是下标函数。我们已经确定这将返回Optional&lt;Optional&lt;Int&gt;&gt;

    这意味着您确实返回了Optional&lt;Optional&lt;Optional&lt;Int&gt;&gt;&gt;,但是正如 Rob Napier 所指出的, “可选链接在使用时删除了额外的可选包装”。

    【讨论】:

      猜你喜欢
      • 2018-06-05
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      • 2015-02-23
      • 1970-01-01
      • 2015-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多