Swift 可选链接的dynamicType与分配不同

Swift 可选链接的dynamicType与分配不同,swift,swift2,dynamictype,optional-chaining,Swift,Swift2,Dynamictype,Optional Chaining,可选链接始终返回可选值 为了反映可以对nil值调用可选链接的事实,可选链接调用的结果始终是可选值,即使您查询的属性、方法或下标返回非可选值也是如此 为什么在操场上这种类型不是可选的 let stringOptEmpty: String? = "" stringOptEmpty?.isEmpty // is true stringOptEmpty?.isEmpty.dynamicType // Bool.Type 但是下面的代码是 let isOk = stringOptE

可选链接始终返回可选值

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

为什么在操场上这种类型不是可选的

let stringOptEmpty: String? = ""
stringOptEmpty?.isEmpty // is true
stringOptEmpty?.isEmpty.dynamicType // Bool.Type
但是下面的代码是

let isOk = stringOptEmpty?.isEmpty.dynamicType
isOk.dynamicType // Optional<Bool.Type>.Type
let isOk=stringOptEmpty?.isEmpty.dynamicType
isOk.dynamicType//Optional.Type
TLDR; 游乐场侧边栏/列将动态解析游乐场中的表达式,可以是分配给变量(可变/不可变)的值,也可以是“自由浮动”的未分配值

第一个示例将
dynamicType
应用于一个值,该值将解析为该特定值的类型(
true.dynamicType
Bool.type

另一方面,您的第二个示例将
dynamicType
应用于一个变量(一个不可变的变量,但我将在这里使用变量来区别于value),该变量必须具有具体的类型,因此将解析为一个可以保存任何类型的包装值(
true
false
)以及
nil
(这里,
nil
是可选的。无),不管变量实际持有什么值。因此,在第二个示例中,
dynamicType
将解析为
可选的.Type


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

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

    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'. */
    
  • 对于不包含赋值的表达式,侧栏中显示的值通常是表达式的结果,例如

在您的第一个示例(第2-3行)中,我们没有赋值,游乐场将在解析表达式的
dynamicType
之前动态解析该表达式的值(/result)。因为我们处理的是选项,所以该值要么只是包装类型的值(在本例中为
true
),或者该值是一个特定于类型的
。无
。即使游乐场显示例如
let a:Int?=nil
的结果,就像侧边栏中的
nil
一样,所显示的值实际上与
不同。无
nil
)与
let b:String=nil

  • 对于
    设a:Int?=nil
    a
    值实际上是
    可选的。无
  • 而对于
    let b:String?=nil
    b
    值是
    可选的。无
考虑到这一点,非
nil
值的解析
dynamicType
自然将是具体的包装类型(在您的示例中,
Bool.type
自然是
true
的类型),而
nil
值的解析
dynamicType
将包括常规可选和包装类型信息

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
我们还可以进一步注意到,操场上任何用偏执语句包装的单独表达式都不会解决任何问题(在侧边栏中)。如果用偏执语句包装表达式,就好像我们逃避了侧边栏的运行时内省(这就解释了为什么用paranethes包装的表达式的
dynamicType
将解析为游乐场无法使用这些表达式的运行时信息)


Tbh,我无法解释为什么会出现这种情况,并将其归类为Swift游乐场的一个特性。

实时列中显示的临时值有时可能会偏离实际值,特别是在显示未分配的可选类型时。但是调试控制台中的
打印
表达式的结果始终显示为e正确的类型。
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
/* .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         */
var a = 4 // shows '4'
(a = 2)   // shows nothing; can't expand or get details in sidebar