当前位置: 首页 > 知识库问答 >
问题:

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

杨飞
2023-03-14

我对此相当困惑。如果我们以UITableView中的方法cell ForRowAtIndexPath:为例,它的方法签名是:

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

其返回值为:

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

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

我从WWDC的谈话中了解到,他们说对于隐式展开的选项:

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

苹果公司将Swift与可可粉和Objective-C结合使用:

当您访问这种可选类型中的值而没有首先安全地展开它时,隐式展开的可选项会检查该值是否丢失。如果值丢失,则会发生运行时错误。

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

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

考虑到似乎没有什么能回答我所看到的这个问题。。。我想这对其他人来说是显而易见的,我只是没有看到,但。。。为什么是这样?

当人们在Swift中使用Objective-C API时,它真的只是为了避免人们使用if let或可选的链接,还是其他什么?

共有2个答案

梅安平
2023-03-14

以下是格雷格·帕克在lists.swift.org的swift用户中的回答:

作为隐式展开的可选导入是一种可用性折衷。大多数Objective-C指针实际上从来都不是零。如果指针为nil,而作者没有检查,则进程会故意停止。这并不比编写Objective-C代码时的行为更糟糕。IUO进口只是权宜之计。从长远来看,每个Objective-C接口都应该被显式注释,以便Swift能够更精确地导入它们。在您自己的代码中,您可以在头文件中使用NS_asked_NONNULL_BEGIN/END。这些标记中的每个未注释的对象指针都是非空的。

微生烨然
2023-03-14

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

当Apple对参数使用隐式展开选项时

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

如果-let,它们可以让你节省一些额外的。在这种情况下,他们知道他们永远不会给你一个nil;在其他情况下,他们不知道,他们希望你检查对象。

它们也允许您返回nil。当然,除非您决定自己调用该函数,否则由他们检查nil的结果。虽然我想不出从您自己的代码调用CellForRowatineXpath的正当理由,但如果您确实进行了调用,您将负责检查nil的返回值。

如果您考虑让参数UITableView nsindepath tableViewindepath之后使用感叹号,或者使用if-let习惯用法。与此选择相比,隐式展开类型看起来是更好的选择。

 类似资料:
  • 请原谅我的无知,我恐怕错过了一些基本的选项理解。我的印象是(隐式展开的可选指示符)保证该类型的变量不为零。然而,这个非常简单的Apple API很少会返回我。 这是一个意外的错误还是Optionals规范的一部分?因为如果这是规范的一部分,我不明白为什么会有选项,而不是变量可以存在或。

  • 我找不到这个职位的申请书http://127.0.0.1:3001/users?name=Slava. 服务器响应“需要名称”。方法getUsers正常工作。数据库工作正常,服务器。js也能工作。我在这里寻找类似的答案,但没有合适的答案。有一些非常古老的答案,但它们并不相关。 这是一项请求:http://127.0.0.1:3001/users?name=bob (我用邮递员送信)

  • 问题内容: 从以下代码 如果我添加一个return语句,它将起作用,并且错误消失了 任何建议都不确定如何在没有虚拟return语句的情况下处理上述问题。 这是我的课程测试 编辑 我已经完成了一个基于操场的简约示例(请复制粘贴以进行测试) 问题答案: 任何建议都不确定如何在没有虚拟return语句的情况下处理上述问题。 您已经很好地解决了问题。匿名函数自动使用单行函数主体作为返回值,因此,要防止这种

  • 问题内容: 我试图制作一个延迟X毫秒执行异步函数的函数。 为了演示的目的,以下是异步函数,该函数采用URL: 目的 我在这里的目标是要有一个函数,它将接受X 的参数,然后每隔X ms调用一次,直到不再有其他参数为止。 基本上,我希望每次调用都用X ms分隔。 例如,假设我连续打电话20次。通常,这20个呼叫将立即进行。我想要的是确保20个呼叫之间都存在Xms的延迟。 暂定 解决这个问题的想法是建立

  • 我正在做一个练习游戏。 我有一个Spring引导/Maven项目连接到MySQL数据库。我能够设置一个api,它只是从我的“所有谜语”表中检索所有内容。它以前工作过,但是现在api返回一个json,其中一些键的值为空。我唯一玩的是Spring引导文件上的application.properties。我在spring.jpa.hibernate.ddl的“更新”和“无”之间跳跃。我到底做错了什么?

  • 问题内容: 在这段代码中,为什么使用结果为no 或循环捕获所有异常然后静默退出?在这种情况下,为什么会有多余的?还是由以下 原因引起的? 假设由触发。什么时候产生的? 如果我手动执行以下操作: 在这种情况下,为什么看不到追溯? 问题答案: 该循环监听明确。 该语句的目的是循环遍历迭代器提供的序列,并使用异常表示当前迭代器已完成。不会捕获被迭代的对象引发的其他异常,只是那个异常。 这是因为正常的预期