我今天遇到了一个奇怪的问题.请看这段代码:
class A {
var button1: UIButton!
var button2: UIButton!
func foo() {
let array = [button1, button2]
}
}
Run Code Online (Sandbox Code Playgroud)
Xcode说这array是[UIButton?]类型.出于某种原因,Swift4将UIButton!元素转换为UIButton?.为什么?
Mil*_*sáľ 15
说明
ImplicitlyUnwrappedOptional不是一个独特的类型,而是Optional具有属性的法线,可以隐式强制声明其值(基于SE-0054):
但是,外观!在属性或变量声明的类型末尾不再表示声明具有IUO类型; 相反,它表示(1)声明具有可选类型,(2)声明具有一个属性,指示可以隐式强制其值.(没有人会写或观察这个属性,但我们会将其称为@_autounwrapped.)此类声明此后称为IUO声明.
因此,当你使用这个:
let array = [button1, button2]
Run Code Online (Sandbox Code Playgroud)
编译器派生的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?
}
Run Code Online (Sandbox Code Playgroud)
解
如果您想获得一个未包装类型的数组,您有两个选择:
首先,正如Guy Kogus在他的回答中建议的那样,使用显式类型而不是让swift派生它:
let array: [UIButton] = [button1, button2]
Run Code Online (Sandbox Code Playgroud)
但是,如果其中一个按钮包含nil,则会导致Unexpectedly found nil崩溃.
虽然使用隐式展开的可选而不是可选(!而不是?)你声称这些按钮中永远不会有nil,但我仍然更喜欢EmilioPelaez在他的评论中提出的第二个更安全的选项.那就是使用(在Swift 4+中)将过滤掉s,如果有的话,并将返回一个unwrapped类型的数组:flatMapcompactMapnil
let array = [button1, button2].flatMap { $0 }
Run Code Online (Sandbox Code Playgroud)
因为UIButton!它不是一种类型,或者更确切地说它是一种UIButton?约定.该!方法总是隐式展开可选项.下列
var x: UIButton!
// Later
x.label = "foo"
Run Code Online (Sandbox Code Playgroud)
是语法糖
var x: UIButton?
// Later
x!.label = "foo"
Run Code Online (Sandbox Code Playgroud)
当您创建它们的数组时.编译器可以选择隐式解包它们并推断[UIButton]或将它们保留为可选和推断[UIButton?].它是两个选项更安全的选择.
| 归档时间: |
|
| 查看次数: |
834 次 |
| 最近记录: |