为什么Objective-C API会隐式返回未包装的选项?

时间:2014-07-14 00:48:54

标签: ios objective-c interop swift optional

我对此感到困惑。例如,如果我们在cellForRowAtIndexPath:中采用方法UITableView,则其方法签名为:

func cellForRowAtIndexPath(_ indexPath: NSIndexPath!) -> UITableViewCell!

它的返回值是:

  

表示表格单元格的对象,如果单元格不可见或indexPath超出范围,则为nil。

这听起来像是使用标准选配件的完美理由。事实上,由于Objective-C中所有基于指针的类型都可以为nil ......似乎所有Objective-C指针类型都应该作为标准选项导入。

我从WWDC的演讲中得知,他们说这是隐含的未解决的选项:

  • 可以明确测试nil
  • 可以直接访问基础值的属性/方法
  • 可以隐式转换为其基础值

来自Apple的Using Swift with Cocoa and Objective-C

  

当您访问此类可选类型的值而不首先安全地展开它时,隐式解包的可选项会检查该值是否缺失。如果缺少该值,则会发生运行时错误。

因此,他们不是将可能的nil值导入Swift作为可选项,而是决定将其导入为声明永远不会为零的东西......但可能是?听起来他们通过这样做完全否定了Swift for Objective-C API中可选类型的安全性。我似乎缺少什么?

他们没有给出编译时错误或警告,而是认为运行时错误更好?这非常令人困惑。

考虑到似乎没有什么能回答我所看到的这个问题...我认为对于其他所有人来说,我只是没有看到,但是......为什么会这样?

当他们在Swift中使用Objective-C API时,是否真的只是为了避免使用if let或可选链接?或者更多?

2 个答案:

答案 0 :(得分:5)

当你在Swift中创建一个隐式解包的可选项时,并不意味着它总是非零:所有这意味着你告诉编译器当你访问它们的属性时,你希望对象是非 - nil。您可以显式检查您引用的对象nil;将其设置为nil也不会导致异常,除非您在此之后尝试访问其任何属性。

当Apple对

的参数使用隐式解包的选项时
func tableView(_ tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!

功能,它们可以节省一些额外的if - let。在这种情况下,他们知道他们从来没有通过你nil;在其他情况下,他们不知道,他们希望你nil - 检查对象。

他们也允许您返回nil。他们应该检查nil的结果,当然,除非您决定自己调用该功能。虽然我无法想出从您自己的代码中拨打cellForRowAtIndexPath的正当理由,但如果您拨打电话,则有责任检查nil的返回值。

如果您考虑替代制作参数UITableView?NSIndexPath?,则所有实现都必须在tableViewindexPath之后使用感叹号,或者使用if - let成语。{{1}} - {{1}}成语。与此选择相比,隐式展开的类型看起来是更好的选择。

答案 1 :(得分:3)

以下是Greg Parker's answerswift-users的lists.swift.org:

  

导入为隐式解包的可选项是一种可用性   的折衷即可。大多数Objective-C指针实际上都不是零。如果指针为nil,并且作者没有检查,那么该过程   故意停止。这并不比你得到的行为更糟​​糕   编写Objective-C代码。       IUO导入旨在成为权宜之计。我 n长期来说,每个Objective-C接口都应该明确注释,以便Swift   可以更精确地导入它们。在您自己的代码中,您可以使用   头文件中的NS_ASSUME_NONNULL_BEGIN / END。每个未注释的   这些标记内的对象指针是非空的。