我知道我们需要在Swift中定义函数的参数,既不是隐式展开的可选参数,也不是可选的,以使其成为非零。但是我不确定隐式展开的可选或可选之间更常见的是什么。
我正在观看 WWDC 2014 Swift interoperability in depth ,并对幻灯片中显示的两个示例感到困惑。基本上它是关于在定义函数时是否应该使用隐式可选或解包参数。
以下是WWDC 2014 Swift interoperability in depth的截图(09:01)
而发言者的引言是
你再次看到这是一个隐含的未包装的可选项,所以你可以 在这里通过一个零块。
请注意, url 和 completionHandler 都是隐式展开选项,我们可以将 nil 传入其中。一切都好!
然而当我检查 UIKit UITableViewCell时,我发现大多数方法都是使用可选参数定义的,例如
init(style: UITableViewCellStyle, reuseIdentifier: String?)
基本上它表明这些参数也可以是零。
似乎?和!尝试建议同样的事情(可以是 nil )。
我理解?意味着我们会将任何值包装到可选值(即使是nil),!表示我们会将其解包如果传入的是可选值。但我不确定是否应该使用!或?。哪个是传统的?
看起来WWDC 2014的视频不太正确或过时。视频的屏幕截图显示了 UIDocument 标头文件,该文件与当前的UIKit标头不同。看起来当时,所有这些都被定义为!。但现在它是?或普通类型。
WWDC 2014 Swift深度互操作性(16:25)
当前标头文件
答案 0 :(得分:4)
?
是Optional<T>
类型!
是ImplicitlyUnwrappedOptional<T>
类型这两种类型都实现了NilLiteralConvertible。这意味着他们有init(nilLiteral: ())
,可以Void
初始化。这可以通过编译器在代码中以合成方式为nil
到NilLiteralConvertible
变量的常规分配。以下是一些代码行,从编译器的角度来看,意思相同:
let sweetOptionalInt: Int? = nil
let semiSweetOptionalInt: Optional<Int> = nil
let unsweetenedOptionalInt: Optional<Int> = Optional<Int>(nilLiteral: Void)
ImplicitlyUnwrappedOptional
也是如此。
所以两者都可以由nil
初始化,但这些类型的行为是不同的:
ImplicitlyUnwrappedOptional
以假设为你打包
当你做一个呼叫对象已经提供(但可能是零
之前),如果不是,则应用程序将因运行时错误而崩溃。Optional
将要求您提供有关如何解包变量的信息。至于之前的互操作性,Objective-C没有办法表达变量的可空性。这就是为什么大多数API都被转换了!这表示“如果你敢的话,继续前进”最近Apple introduced Objective-C的可空性注释。 Apple使用这些注释来增加他们的API,因此现在使用Swift中具有额外可空性指导的方法更容易,更安全。
答案 1 :(得分:3)
你不太对劲。 “!”是“强制解包”操作员。它说“这是一个可选的,但我保证当这个代码运行时,它不会是零。”如果你错了,你会崩溃。
如果你正在编写一个带有合法nil参数的函数,请使用“?”,这使它成为一个可选项。然后在函数的代码中,你必须处理它为零的情况。