在Swift函数签名中,参数后的!
表示什么?更具体地说,这是指参数在传入之前需要展开,还是在传入时(自动)展开.下面是一个例子:
func annotationButtonTUI(sender: UIButton!) { }
在这种情况下,该函数是UIButton的目标,因此无论!
发生什么,都会自动发生.
我的 idea 是,这意味着你可以期待一个sender
个展开的对象,所以你不需要try 展开它.
在Swift函数签名中,参数后的!
表示什么?更具体地说,这是指参数在传入之前需要展开,还是在传入时(自动)展开.下面是一个例子:
func annotationButtonTUI(sender: UIButton!) { }
在这种情况下,该函数是UIButton的目标,因此无论!
发生什么,都会自动发生.
我的 idea 是,这意味着你可以期待一个sender
个展开的对象,所以你不需要try 展开它.
这并不是完全重复——除了在其他地方的使用之外,隐式打开in function signatures个选项还有一些微妙之处.
在从ObjC导入的API中可以看到隐式展开的选项,因为这是一个对象的最接近的Swift近似值,该对象预计会在那里,但可能为零.这是对导入API的一种折衷——您可以像在ObjC中一样直接处理这些变量,并且可以使用Swift可选语法测试它们是否为零.(WWDC14的Advanced Interoperability talk篇文章中有更多关于苹果的理由.)这种模式也适用于Interface Builder插入的IBAction
个声明,因为这些方法实际上也是从ObjC代码中调用的.
正如您所怀疑的那样,当从ObjC桥接时,Swift将可能的nil封装在可选值中,但函数实现声明中的!
会将该值展开,以便您可以直接使用它.(风险自负.)
自Swift 1.2(2015年 spring 的Xcode 6.2)以来,ObjC API可以用nonnull
和nullable
进行注释,在这种情况下,这些API的Swift接口使用非可选类型或完全可选类型.(自从Swift 2.0/Xcode 7.0以来,几乎所有苹果的API都经过审计,使用了可空性注释,因此他们的Swift签名不再使用太多注释.)
关于这一点,不太为人所知的是,当您实现自己的Swift函数时,您可以自由地更改参数的可选性,这些函数会被ObjC调用.如果希望编译器强制执行action方法中的sender
永远不能为nil,则可以从参数类型中go 掉!
.如果希望编译器确保始终测试参数,请将!
改为?
.