根据SE-0054,ImplicitlyUnwrappedOptional<T>
不再是唯一类型;只有Optional<T>
现在。
声明仍然可以被注释为隐含的未包装的可选内容T!
,但这只是添加一个隐藏的属性来通知编译器,在需要他们的未包装类型的上下文中,它们的值可能被强制包装T
; 他们的实际类型是现在T?
。
因此,您可以想到以下声明:
var str: String!
实际看起来像这样:
@_implicitlyUnwrapped
var str: String?
只有编译器可以看到此@_implicitlyUnwrapped
属性,但是它允许的是在str
需要a String
(其未包装类型)的上下文中隐式展开的值:
let x: String = str
print(str.count)
但是在所有其他str
可以作为强选项进行类型检查的情况下,它将是:
let x = str
let y: Any = str
print(str)
而且,与强制展开相比,编译器将始终更喜欢将其视为此类。
如提案所述(强调我的意思):
如果可以使用强可选类型对表达式进行显式类型检查,则它将为。但是,如果需要的话,类型检查器将转为强制使用可选。此行为的结果是,引用声明为的值的任何表达式的结果T!
将具有typeT
或typeT?
。
对于字符串插值,在后台,编译器使用_ExpressibleByStringInterpolation
协议中的此初始化程序来评估字符串插值段:
init<T>(stringInterpolationSegment expr: T)
因此,当您的代码隐式调用时:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
由于str
的实际类型为String?
,因此默认情况下,编译器将推断出通用占位符T
为。因此,str
不会强行解开的值,您最终将看到可选内容的描述。
如果希望在字符串插值中使用时将IUO强制展开,则可以简单地使用force unwrap运算符!
:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str!)")
或者您可以强制使用其非可选类型(在本例中为String
),以强制编译器为您隐式强制对其进行解包:
print("The following should not be printed as an optional: \(str as String)")
如果str
为,这两个当然都会崩溃nil
。