【发布时间】:2016-04-24 13:56:39
【问题描述】:
我很困惑地发现下面的代码根本拒绝崩溃,典型的“Unexpectedly found nil while unwrapping an Optional value”你期望强制解包bar的异常。
struct Foo {
var bar: Bar?
}
struct Bar {}
var foo = Foo()
debugPrint(foo.bar) // nil
debugPrint(foo.bar!.dynamicType) // _dynamicType.Bar
似乎dynamicType以某种方式能够回退到bar的定义类型——而不会崩溃。
请注意,这仅在 Bar 定义为 value 类型(如 @dfri says)、Foo 是 struct 或 final class(如 pointed out by @MartinR ) & foo 是可变的。
我最初确实认为它可能只是编译器优化,因为 bar 的类型在编译时是已知的,因此强制展开可以被优化掉 - 但它也会在 @987654333 时崩溃@ 定义为final class。此外,如果我将“优化级别”设置为-Onone,它仍然有效。
我倾向于认为这是一个奇怪的错误,但希望得到一些确认。
这是 dynamicType 的错误或功能,还是我只是在这里遗漏了什么?
(使用带有 Swift 2.2 的 Xcode 7.3)
Swift 4.0.3 更新
这在 Swift 4.0.3 中仍然可以重现(用一个更小的例子):
var foo: String?
print(type(of: foo!)) // String
这里我们使用dynamicType 的继任者type(of:) 来获取动态类型;和前面的例子一样,它不会崩溃。
【问题讨论】:
-
请注意,它与
class Foo崩溃,但不是 与final class Foo... :) -
您说的是在编译时知道
dynamicType的结果的情况。!可能是一个错误。 -
我想知道它是否与使模式匹配工作的同一件事有关 - 这可能听起来很愚蠢,但我的意思是,它能够像
sealed一样使用提示final并工作倒退……对我来说,这闻起来像是一种无意的行为,但我知道吗:) -
@Sulthan 我确实认为这可能只是编译器优化,因为
bar的类型在编译时是已知的,因此可以优化强制展开 - 但是当Bar被定义为final class时它会崩溃,所以我不太确定! -
似乎允许上述内容在没有运行时异常的情况下运行的一个关键是
bar是 任何类型的值 类型,而不仅仅是结构或枚举(并且foo是一个可变的)。例如。struct Foo { var bar: Int? }; var foo = Foo()同样允许在强制解包(空)可选foo.bar上使用dynamicType(而例如bar作为基础:sNSNumber引用类型将产生崩溃)。
标签: swift