今天遇到一个奇怪的问题。请看这段代码:
class A {
var button1: UIButton!
var button2: UIButton!
func foo() {
let array = [button1, button2]
}
}
Xcode 表示 array
是 [UIButton?]
类型。出于某种原因,Swift4 将 UIButton!
元素转换为 UIButton?
。为什么?
最佳答案
解释
ImplicitlyUnwrappedOptional
不是一个独特的类型,而是一个普通的 Optional
声明其值的属性可能会被隐式强制(基于 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. (No human would ever write or observe this attribute, but we will refer to it as @_autounwrapped.) Such a declaration is referred to henceforth as an IUO declaration.
因此当你使用它时:
let array = [button1, button2]
编译器导出 array
输入 [UIButton?]
, 因为 button1
的类型和 button2
是Optional<UIButton>
, 不是 ImplicitlyUnwrappedOptional<UIButton>
(即使只有一个按钮是可选的,它也会派生出可选类型)。
阅读更多 SE-0054 .
旁注:
此行为与arrays
没有真正相关, 在以下示例中 button2
的类型将派生到 UIButton?
即使有 !
button
中设置了一个值:
var button: UIButton! = UIButton()
func foo() {
let button2 = button // button2 will be an optional: UIButton?
}
解决方案
如果你想得到一个解包类型的数组,你有两个选择:
首先,如Guy Kogus在他的回答中建议,使用显式类型而不是让 swift 派生它:
let array: [UIButton] = [button1, button2]
但是,如果碰巧其中一个按钮包含 nil
,它会导致Unexpectedly found nil
崩溃。
虽然通过使用隐式展开的可选而不是可选(!
而不是 ?
)你声称这些按钮中永远不会有 nil,但我仍然更喜欢第二个更安全的选项EmilioPelaez 建议在他的评论中。即使用flatMap
( compactMap
在 Swift 4+ 中)将过滤掉 nil
s,如果有的话,将返回一个未包装类型的数组:
let array = [button1, button2].flatMap { $0 }
关于ios - 为什么 Swift4 会转换一个 UIButton 数组!到 [UIButton?] 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54054433/