如何在函数中指定参数可以在Swift中为nil

时间:2021-04-25 21:46:57

I know we need to define the parameter of function in Swift to be neither implicit unwrapped optional or optional, to make it non-nil. However I am not sure what is more conventional between implicit unwrapped optional or optional.

我知道我们需要在Swift中定义函数的参数既不是隐式解包可选也不是可选,以使其为非零。但是我不确定隐式解包的可选或可选之间的更常规。

I am watching WWDC 2014 Swift interoperability in depth and a bit confused with two examples shown in the slides. Basically it is about whether we should use implicit optional or unwrap parameters when defining function.

我正在深入观察WWDC 2014 Swift互操作性,并且与幻灯片中显示的两个示例有点混淆。基本上它是关于我们在定义函数时是否应该使用隐式可选或解包参数。


Example from Video

Below is the screenshot from that WWDC 2014 Swift interoperability in depth (At 09:01) 如何在函数中指定参数可以在Swift中为nil And the quote from the speaker is

下面是WWDC 2014 Swift深度互操作性的截图(在09:01),发言者的引用是

You see again this is an implicit unwrapped optional, so that you can pass a nil block in here.

你再次看到这是一个隐式的unwrapped可选项,所以你可以在这里传递一个nil块。

Notice here both url and completionHandler are implicit unwrapped optionals, and we can pass in nil into it. All good!

请注意,url和completionHandler都是隐式的unwrapped选项,我们可以将nil传入其中。都好!


Example from Header file

However when I check UIKit UITableViewCell, I find most of the methods are defined with optional parameters, such as

但是当我检查UIKit UITableViewCell时,我发现大多数方法都是用可选参数定义的,例如

    init(style: UITableViewCellStyle, reuseIdentifier: String?)

And basically it is suggesting those parameters can be nil too.

基本上它表明这些参数也可以是零。

Seems like both ? and ! try to suggest the same thing (it can be nil).

好像两者都有?而且!试着建议同样的事情(它可以是零)。

I understand that ? means we will wrap whatever value to optional value (even for nil), and ! means we will unwrap it if what is passed in is an optional value. But I am not sure whether we should use ! or ?. And which is conventional?

我明白那个 ?意味着我们将任何值包装到可选值(即使是nil),并且!意味着如果传入的是可选值,我们将解包它。但我不确定是否应该使用!要么 ?。哪个是传统的?


Update

Looks like the video from WWDC 2014 is not quite correct or out-dated. Screenshot from the video shows UIDocument header file, which was different from the current UIKit header. It looks like at that time, all of them were defined as !. But now it is either ? or plain type.

看起来WWDC 2014的视频不太正确或过时。视频的屏幕截图显示了UIDocument头文件,它与当前的UIKit头不同。看起来当时,所有这些都被定义为!但现在它是?或普通类型。

WWDC 2014 Swift interoperability in depth (At 16:25)

WWDC 2014 Swift深度互操作性(16:25)

如何在函数中指定参数可以在Swift中为nil

Current header file

当前头文件

如何在函数中指定参数可以在Swift中为nil

2 个解决方案

#1


3  

  • ? is a shortcut for Optional<T> type
  • ?是Optional 类型的快捷方式

  • ! is a shortcut for ImplicitlyUnwrappedOptional<T> type
  • !是ImplicitlyUnwrappedOptional 类型的快捷方式

Both types implement NilLiteralConvertible. This mean they have init(nilLiteral: ()) and can be initialized by Void. This could be syntatically-sugard in code by compiler into regular assignement of nil to a NilLiteralConvertible variable. Here are some code lines that from compiler standpoint mean the same:

这两种类型都实现了NilLiteralConvertible。这意味着他们有init(nilLiteral:())并且可以通过Void初始化。这可以通过编译器在代码中以合成方式进行,并将nil定期分配给NilLiteralConvertible变量。以下是一些代码行,从编译器的角度来看意味着相同:

 let sweetOptionalInt: Int? = nil
 let semiSweetOptionalInt: Optional<Int> = nil
 let unsweetenedOptionalInt: Optional<Int> = Optional<Int>(nilLiteral: Void)

The same is true for ImplicitlyUnwrappedOptional.

ImplicitlyUnwrappedOptional也是如此。

So both could be initialized by nil, but behaviors of these types are different:

所以两者都可以用nil初始化,但这些类型的行为是不同的:

  • ImplicitlyUnwrappedOptional do unwrapping for you with an assumption when you do a call object is already provided (but could be nil before), so if it is not then application will crash with a runtime error.
  • ImplicitlyUnwrappedOptional会在您提供调用对象的情况下为您进行解包(但之前可能为nil),因此如果不是,则应用程序将因运行时错误而崩溃。

  • Optional will require you to provide information how to unwrap variables.
  • 可选将要求您提供有关如何解包变量的信息。

As for interoperability while ago Objective-C didn't have a way to express nullability of variables. This is why most of APIs was converted with ! that stands for "proceed further if you dare" Recently Apple introduced nullability annotations for Objective-C. Apple augumented their APIs with these annotations, so now it is easier and safer to use methods with an extra nullability guidance in Swift.

至于之前的互操作性,Objective-C没有办法表达变量的可空性。这就是大多数API转换为的原因!代表“如果你敢于继续前进”,最近Apple推出了针对Objective-C的可空性注释。 Apple使用这些注释来增加他们的API,因此现在使用Swift中具有额外可空性指导的方法更容易,更安全。

#2


3  

You aren't quite right. "!" is the "force unwrap" operator. It says "This is an optional, but I guarantee that when this code runs, it won't be nil." If you are wrong, you crash.

你不太对劲。 “!”是“强制解包”运算符。它说“这是一个可选的,但我保证当这个代码运行时,它不会是零。”如果你错了,你会崩溃。

if you are writing a function that takes a parameter that can be legitimately nil, use "?", which makes it an Optional. Then in the code of your function, you have to handle the case where it is nil.

如果你正在编写一个带有合法nil参数的函数,请使用“?”,这使它成为一个可选项。然后在函数的代码中,你必须处理它为零的情况。

#1


3  

  • ? is a shortcut for Optional<T> type
  • ?是Optional 类型的快捷方式

  • ! is a shortcut for ImplicitlyUnwrappedOptional<T> type
  • !是ImplicitlyUnwrappedOptional 类型的快捷方式

Both types implement NilLiteralConvertible. This mean they have init(nilLiteral: ()) and can be initialized by Void. This could be syntatically-sugard in code by compiler into regular assignement of nil to a NilLiteralConvertible variable. Here are some code lines that from compiler standpoint mean the same:

这两种类型都实现了NilLiteralConvertible。这意味着他们有init(nilLiteral:())并且可以通过Void初始化。这可以通过编译器在代码中以合成方式进行,并将nil定期分配给NilLiteralConvertible变量。以下是一些代码行,从编译器的角度来看意味着相同:

 let sweetOptionalInt: Int? = nil
 let semiSweetOptionalInt: Optional<Int> = nil
 let unsweetenedOptionalInt: Optional<Int> = Optional<Int>(nilLiteral: Void)

The same is true for ImplicitlyUnwrappedOptional.

ImplicitlyUnwrappedOptional也是如此。

So both could be initialized by nil, but behaviors of these types are different:

所以两者都可以用nil初始化,但这些类型的行为是不同的:

  • ImplicitlyUnwrappedOptional do unwrapping for you with an assumption when you do a call object is already provided (but could be nil before), so if it is not then application will crash with a runtime error.
  • ImplicitlyUnwrappedOptional会在您提供调用对象的情况下为您进行解包(但之前可能为nil),因此如果不是,则应用程序将因运行时错误而崩溃。

  • Optional will require you to provide information how to unwrap variables.
  • 可选将要求您提供有关如何解包变量的信息。

As for interoperability while ago Objective-C didn't have a way to express nullability of variables. This is why most of APIs was converted with ! that stands for "proceed further if you dare" Recently Apple introduced nullability annotations for Objective-C. Apple augumented their APIs with these annotations, so now it is easier and safer to use methods with an extra nullability guidance in Swift.

至于之前的互操作性,Objective-C没有办法表达变量的可空性。这就是大多数API转换为的原因!代表“如果你敢于继续前进”,最近Apple推出了针对Objective-C的可空性注释。 Apple使用这些注释来增加他们的API,因此现在使用Swift中具有额外可空性指导的方法更容易,更安全。

#2


3  

You aren't quite right. "!" is the "force unwrap" operator. It says "This is an optional, but I guarantee that when this code runs, it won't be nil." If you are wrong, you crash.

你不太对劲。 “!”是“强制解包”运算符。它说“这是一个可选的,但我保证当这个代码运行时,它不会是零。”如果你错了,你会崩溃。

if you are writing a function that takes a parameter that can be legitimately nil, use "?", which makes it an Optional. Then in the code of your function, you have to handle the case where it is nil.

如果你正在编写一个带有合法nil参数的函数,请使用“?”,这使它成为一个可选项。然后在函数的代码中,你必须处理它为零的情况。