TLDR;
操场侧边栏/列将动态解析操场中的表达式,无论是分配给变量(可变/不可变)的值还是只是“自由浮动”的非分配值。
您的第一个示例适用dynamicType
于value,它将解析为该特定值的类型(true.dynamicType
: Bool.Type
)。
另一方面,您的第二个示例适用dynamicType
于变量(不可变,但我将在此处使用variable与value不同),该变量必须具有具体类型,因此将解析为可以容纳任何类型的类型包装的值(true
或false
)以及nil
(这里,nil
特别是,Optional<Bool.Type>.None
),无论变量实际持有什么值。因此,将在您的第二个示例中dynamicType
解析为。Optional<Bool.Type>.Type
细节
在 Playground 侧边栏/列中显示的值一般遵循以下显示规则:
对于赋值表达式,侧边栏中显示的值是赋值的值,例如
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'. */
对于不包含赋值的表达式,侧边栏中显示的值通常是表达式的结果,例如
true // shows 'true'
1 > 3 // shows 'false'
let c = 3
c // shows '3'
c.dynamicType // shows 'Int.Type'
在您的第一个示例(第 2-3 行)中,我们没有赋值,并且 Playground 将在解析该值之前动态解析表达式的值(/result) dynamicType
。由于我们正在处理可选项,因此该值或者只是包装类型的值(在本例中为true
),或者该值是特定于类型 .None
的。即使操场在侧边栏中显示了例如let a: Int? = nil
as的结果,显示nil
的值实际上与say不同.None
( )nil
let b: String = nil
- 因为
let a: Int? = nil
的值a
实际上Optional<Int.Type>.None
是_
- 而对于
let b: String? = nil
,的值为b
Optional<String.Type>.None
考虑到这一点,dynamicType
非nil
值的解析很自然将是具体的包装类型(在您的示例中,Bool.Type
自然是 的类型true
),而值的解析dynamicType
将nil
包括一般可选和包装类型信息.
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>
(不管变量是持有nil
还是非nil
值)。这是您在第二个示例中展示的情况:dynamicType
变量的(这里是不可变的,但使用变量 与value不同)isOk
是可以同时包含.None
and的类型,.Some<T>
无论变量的实际值是什么,因此dynamicType
解析为这种类型;Optional<Bool.Type>.Type
.
在括号中包装表达式逃脱了 Swift Playground 的运行时自省?
有趣的是,如果一个表达式在应用之前被包裹在括号中.dynamicType
,那么操场侧边栏会将.dynamicType
包裹的表达式解析为表达式的类型,就好像它的实际值是未知的一样。例如,(...)
in(...).dynamicType
被视为具有具体类型的变量,而不是运行时解析的值。
/* .Some case (non-nil) */
foo?.bar // true
(foo?.bar).dynamicType /* Optional<Bool>.Type <-- as if (...)
is a _variable_ of unknown value */
/* .None case (nil) */
foo = nil
(foo?.bar).dynamicType /* Optional<Bool>.Type <-- as if (...)
is a _variable_ of unknown value */
我们可以进一步注意到,在操场上用括号括起来的任何单独的表达式根本不会解决任何问题(在侧边栏中)。如果将表达式包装在括号中,就好像我们逃避了侧边栏:s 运行时自省(这可以解释为什么dynamicType
用括号括起来的表达式将解析,就好像操场不能使用这些表达式的运行时信息一样)
var a = 4 // shows '4'
(a = 2) // shows nothing; can't expand or get details in sidebar
Tbh,我无法解释为什么会这样,并将其归类为 Swift 游乐场的一个特点。