在Xcode 8中隐式解包可选项的赋值

6
在Xcode 8的发布版本中,我发现了一个奇怪的场景。
以下是代码:
let implicitlyUnwrappedOptionalString: String! = "implicitlyUnwrappedOptionalString"
let foo = implicitlyUnwrappedOptionalString

print(implicitlyUnwrappedOptionalString)
print(foo)

这是结果:

implicitlyUnwrappedOptionalString
Optional("implicitlyUnwrappedOptionalString")

上述内容表明,当我将一个“隐式解包可选类型”赋值给一个没有明确类型的变量时,该类型会被推断为可选类型,而不是其原本的类型,即“隐式解包可选类型”。
我的Xcode已经更新到8版本。有人可以在Xcode 7.x中验证这种行为吗?
这个变化是由于Swift版本的改变还是Xcode的改变所导致的?

没错,这种情况在 Xcode 7/Swift 2 中并不会发生。我在使用 Xcode 8 Beta 版本时也注意到了这一点。毫无疑问,这是 Swift 3 的一个特性,与所使用的 SDK 无关。 - Federico Zanetello
1个回答

12
这是Swift 3中实施的SE-0054废除隐式展开可选类型的结果。摘自该提案(已加重点):

However, the appearance of ! at the end of a property or variable declaration's type no longer indicates that the declaration has IUO type; rather, it indicates that (1) the declaration has optional type, and (2) the declaration has an attribute indicating that its value may be implicitly forced. ...

If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary. The effect of this behavior is that the result of any expression that refers to a value declared as T! will either have type T or type T?. For example, in the following code:

let x: Int! = 5
let y = x
let z = x + 0

… x is declared as an IUO, but because the initializer for y type checks correctly as an optional, y will be bound as type Int?. However, the initializer for z does not type check with x declared as an optional (there's no overload of + that takes an optional), so the compiler forces the optional and type checks the initializer as Int.

在你的情况下,这个任务
let foo = implicitlyUnwrappedOptionalString

使得foo成为一个强制可选类型,例如提案中的let y = x示例。
您可以通过添加显式类型注释将foo变为隐式解包可选类型。
let foo: String! = implicitlyUnwrappedOptionalString

但通常情况下,您应该尝试从代码中摆脱IUO,就像同一提案中所述:

除了一些特定的场景外,可选项始终是更安全的选择,我们希望鼓励人们使用它们而不是IUO。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接