在Swift函数签名中,参数后的!
意味着什么?更具体地说,它是否意味着参数需要在传入之前解开,或者在传入时自动解包(这是一个例子:
func annotationButtonTUI(sender: UIButton!) { }
在这种情况下,该函数是UIButton的目标,因此!
发生的任何事情都会自动发生。
我的想法是,这意味着您可以期待一个未打开的sender
对象,这样您就不需要尝试打开它了。
答案 0 :(得分:37)
这并不重复 - 除了在其他地方使用外,在函数签名中隐式解包选项还有一些微妙之处。
你会在从ObjC导入的API中看到隐式解包的选项,因为它是预期存在的对象的最接近的Swift近似,但可以是零。它是导入API的折衷方案 - 您可以像在ObjC中一样直接处理这些变量,并且可以使用Swift可选语法测试它们为nil。 (更多关于Apple在WWDC14的Advanced Interoperability talk中的基本原理。)此模式也适用于Interface Builder插入的IBAction
声明,因为这些方法有效从ObjC代码调用。
正如您似乎所怀疑的那样,当从ObjC桥接时,Swift将可能的nil包装在可选项中,但是函数实现声明中的!
会解除该值,以便您可以直接使用它。 (风险自负。)
自Swift 1.2(2015年春季的Xcode 6.2)以来,ObjC API可以使用nonnull
和nullable
进行注释,在这种情况下,这些API的Swift接口使用非可选类型或完全可选的类型。 (自从Swift 2.0 / Xcode 7.0以来,几乎所有Apple的API都经过审核以使用可空性注释,因此他们的Swift签名不再使用!
了。)
对此不太了解的是,当您实现由ObjC调用的自己的Swift函数时,您可以自由地更改参数的可选性。如果您希望编译器强制执行操作方法中的sender
永远不能为零,则可以从参数类型中取消!
。如果您希望编译器确保始终测试参数,请将!
更改为?
。
答案 1 :(得分:8)
Swift方法签名中的类型声明后的感叹号表示参数是Implicitly Unwrapped Optional。这意味着它是Optional type(通常在类型后用?
表示),每次在方法体中访问它时都会被解包。而不是传入它。就好像你使用forced unwrapping - sender!.titleLabel
- 每次使用它时,你不必每次都输入感叹号 - 因此隐式解包可选。 / p>
来自Using Swift with Cocoa and Objective-C, section Working with nil:
因为Objective-C没有保证对象是非nil,所以Swift在参数类型中使所有类,并且在导入的Objective-C API中返回类型是可选的。在使用Objective-C对象之前,应检查以确保它不会丢失。
隐式解包可选允许您在Swift代码中将其视为普通值类型,并且当nil
{{1}}将因运行时错误而中断程序时需要访问它。您可以使用if statements optional binding来防范这种情况
或optional chaining。
隐式解包的选项是务实的妥协,使混合环境中的工作必须与现有的Cocoa框架及其约定更加愉快,同时还允许逐步迁移到更安全的编程范例 - 没有空指针 - 由Swift编译器强制执行。您将在Cocoa API中遇到它们,但use cases for them in pure Swift中还讨论了一些Why create "Implicitly Unwrapped Optionals"?