Kei*_*wan 71 string string-interpolation swift swift3
为什么在Swift 3中使用字符串插值时,隐式解包的选项不会被解包?
示例:在操场中运行以下代码
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
Run Code Online (Sandbox Code Playgroud)
产生这个输出:
The following should not be printed as an optional: Optional("Hello")
Run Code Online (Sandbox Code Playgroud)
当然我可以用+运算符连接字符串,但我在我的应用程序中几乎无处不在使用字符串插值,现在因为这个而无法工作(bug?).
这甚至是一个bug还是他们故意用Swift 3改变这种行为?
Ham*_*ish 71
根据SE-0054,ImplicitlyUnwrappedOptional<T>不再是一个独特的类型; 只有Optional<T>现在.
声明仍然允许注释为隐式解包的选项T!,但这样做只会添加一个隐藏属性来通知编译器,它们的值可能会在需要解包类型的上下文中被强制解包T; 他们的实际类型现在T?.
所以你可以想到这个宣言:
var str: String!
Run Code Online (Sandbox Code Playgroud)
实际上看起来像这样:
@_implicitlyUnwrapped // this attribute name is fictitious
var str: String?
Run Code Online (Sandbox Code Playgroud)
只有编译器才能看到这个@_implicitlyUnwrapped属性,但是它允许的是在str需要String(它的unwrapped类型)的上下文中隐式展开的值:
// `str` cannot be type-checked as a strong optional, so the compiler will
// implicitly force unwrap it (causing a crash in this case)
let x: String = str
// We're accessing a member on the unwrapped type of `str`, so it'll also be
// implicitly force unwrapped here
print(str.count)
Run Code Online (Sandbox Code Playgroud)
但在所有其他情况下,str可以将类型检查为强选项,它将是:
// `x` is inferred to be a `String?` (because we really are assigning a `String?`)
let x = str
let y: Any = str // `str` is implicitly coerced from `String?` to `Any`
print(str) // Same as the previous example, as `print` takes an `Any` parameter.
Run Code Online (Sandbox Code Playgroud)
并且编译器总是倾向于将其视为强制展开.
正如提案所说(强调我的):
如果可以使用强可选类型显式地检查表达式,那么它将是.但是,如果需要,类型检查器将回退到强制可选.此行为的结果是任何表达式的结果都引用了声明为
T!具有类型T或类型的值T?.
在字符串插值方面,编译器使用_ExpressibleByStringInterpolation协议中的初始化程序来评估字符串插值段:
/// Creates an instance containing the appropriate representation for the
/// given value.
///
/// Do not call this initializer directly. It is used by the compiler for
/// each string interpolation segment when you use string interpolation. For
/// example:
///
/// let s = "\(5) x \(2) = \(5 * 2)"
/// print(s)
/// // Prints "5 x 2 = 10"
///
/// This initializer is called five times when processing the string literal
/// in the example above; once each for the following: the integer `5`, the
/// string `" x "`, the integer `2`, the string `" = "`, and the result of
/// the expression `5 * 2`.
///
/// - Parameter expr: The expression to represent.
init<T>(stringInterpolationSegment expr: T)
Run Code Online (Sandbox Code Playgroud)
因此,当您的代码隐式调用时:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
Run Code Online (Sandbox Code Playgroud)
正如str实际类型一样String?,默认情况下编译器将推断通用占位符T.因此,值str不会被强制解包,您最终会看到可选的描述.
如果你希望在字符串插值中使用IUO强制解包,你可以简单地使用强制解包操作符!:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str!)")
Run Code Online (Sandbox Code Playgroud)
或者你可以强制它的非可选类型(在这种情况下String),以强制编译器隐式强制为你打开它:
print("The following should not be printed as an optional: \(str as String)")
Run Code Online (Sandbox Code Playgroud)
这两者,当然会崩溃,如果str是nil.
| 归档时间: |
|
| 查看次数: |
5483 次 |
| 最近记录: |