可选链接的dynamicType与赋值不同

时间:2016-05-28 09:56:50

标签: swift swift2 dynamictype optional-chaining

可选链接返回始终可选值。

  

为了反映可以在nil值上调用可选链接的事实,可选链接调用的结果始终是可选值,即使您要查询的属性,方法或下标返回非可选值。

     

The Swift Programming Language

为什么heck在操场上的类型不是可选的?

let stringOptEmpty: String? = ""
stringOptEmpty?.isEmpty // is true
stringOptEmpty?.isEmpty.dynamicType // Bool.Type

但是以下代码是

let isOk = stringOptEmpty?.isEmpty.dynamicType
isOk.dynamicType // Optional<Bool.Type>.Type

1 个答案:

答案 0 :(得分:4)

TLDR;

操场边栏/列将动态解析操场中的表达式,无论是分配给变量(mutables / immutables)的值还是仅仅是“自由浮动”的非指定值。

您的第一个示例将dynamicType应用于,该值将解析为该特定值的类型true.dynamicType:{{1 }})。

另一方面,你的第二个例子将Bool.Type应用于变量(一个不可变的,但我会在这里使用变量来区别于< em> value ),它必须具有具体类型,因此将解析为可以包含任何类型的包装值(dynamicTypetrue)以及{{1 (此处,false,具体而言,nil),无论变量实际保持什么值。因此,nil将在您的第二个示例中解析为Optional<Bool.Type>.None

详细信息

游乐场侧栏/栏中显示的值通常遵循以下显示规则:

  • 对于赋值表达式,侧栏中显示的值是指定的值,例如

    dynamicType
  • 对于不包含赋值的表达式,侧栏中显示的值通常是表达式的结果,例如

    Optional<Bool.Type>.Type

在您的第一个示例(第2-3行)中,我们没有赋值,并且在解析var a = 4 // shows '4' a = 2 // shows '2' let b: () = (a = 3) /* shows '()': the _value_ assigned to 'b', which is the _result_ of the assignment 'a = 3', to which a _side effect_ is that 'a' is assigned the value '3'. */ 之前,操场将动态解析表达式的(/ result)那个价值。由于我们正在处理选项,因此或者只是包装类型的值(在本例中为true // shows 'true' 1 > 3 // shows 'false' let c = 3 c // shows '3' c.dynamicType // shows 'Int.Type' ),或者值是类型特定的 dynamicType。即使操场上显示例如{/ 1}}的结果仅为侧边栏中的true,显示的值实际上与.None let a: Int? = nil nil不同{/ 1}} p>

  • 对于.Nonenil 实际上是let b: String = nil
  • 而对于let a: Int? = nila Optional<Int.Type>.None

考虑到这一点,很明显,非let b: String? = nil 的已解决b将是具体的包裹类型(在例如,Optional<String.Type>.None自然是dynamicType的类型,而nil值的已解析Bool.Type将包括常规可选和包装类型信息。

true

现在,如果将值赋值给变量,那么变量必然具有一个具体类型。由于我们在运行时分配的值可以是dynamicTypenil,因此变量的类型必须是可以保存这两种情况的值的类型,因此,{{ 1}}(忽略变量是保持struct Foo { let bar: Bool = true } var foo: Foo? = Foo() /* .Some<T> case (non-nil) */ foo?.bar // true <-- _expression_ resolves to (results in) the _value_ 'true' foo?.bar.dynamicType // Bool.Type <-- dynamic type of the _result of expression_ true.dynamicType // Bool.Type <-- compare with this /* .None case (nil) */ foo = nil foo?.bar.dynamicType // nil <-- _expression_ resolves to the _value_ 'Optional<Foo.Type>.None' Optional<Foo.Type>.None.dynamicType // Optional<Foo.Type>.Type <-- compare with this 还是非.None值。这是您在第二个示例中显示的情况:变量的.Some<T> (此处为不可变,但使用变量不同>值Optional<T.Type>是可以同时包含nilnil的类型,无论变量的实际值是什么,因此dynamicType可以解析这种类型; isOk

在parantheses中包装表达式会逃避Swift Playground的运行时内省吗?

有趣的是,如果在应用.None之前将表达式包装在parantheses中,那么操场侧边栏会将包装表达式的.Some<T>解析为表达式的 type ,如如果它的实际值是未知的。例如,dynamicType中的Optional<Bool.Type>.Type被视为具有具体类型而不是运行时解析值的变量。

.dynamicType

我们可以进一步注意到,在操场上的parantheses中包含的任何单独的表达都不会解析为任何东西(在侧边栏中)。就像我们逃避侧边栏:s运行时内省是否将表达式包装在parantheses中(这可以解释为什么包含在parantheses中的.dynamicType表达式将解析为操场无法使用这些表达式的运行时信息)

(...)

Tbh,我无法解释为什么会这样,并将其归类为Swift游乐场的特色。