当前位置: 首页 > 面试题库 >

Swift可选链接在关闭时不起作用

萧树
2023-03-14
问题内容

我的代码如下所示。我的课有一个可选的var

var currentBottle : BottleLayer?

BottleLayer有一个方法jiggle()

这段代码使用可选的链接,可以在我的类中很好地编译:

self.currentBottle?.jiggle()

现在,我想构造一个使用相同代码的闭包:

let clos = {() -> () in self.currentBottle?.jiggle()}

但是我得到一个编译错误:

找不到成员“ jiggle”

作为解决方法,我可以强制展开

let clos = {() -> () in self.currentBottle!.jiggle()}

或者我当然可以使用成熟的可选绑定,但是我宁愿不使用。我确实认识到可选链接只是语法糖,但是很难看出为什么这种语法糖会因为在处理程序中而停止工作(当然,这可能是有原因的,但无论如何这都是令人惊讶的)

也许其他人对此有所了解并对此有所考虑?谢谢。


问题答案:

这不是错误。只是您的关闭类型有误。正确的类型应返回一个可选值Void以反映可选的链接:

let clos = { ()->()? in currentBottle?.jiggle() }

问题的细节:

  • 您将闭包声明为返回的闭包Void(即->())。
  • 但是,请记住,就像每次使用可选链接一样,整个表达式的返回类型都是 可选类型 。因为如果存在,您的关闭可以 返回VoidcurrentBottle …… 或者nil如果不存在,则 可以返回

因此正确的语法是使您的闭包返回Void?(或()?)而不是简单的Void

class BottleLayer {
    func jiggle() { println("Jiggle Jiggle") }
}
var currentBottle: BottleLayer?
currentBottle?.jiggle() // OK
let clos = { Void->Void? in currentBottle?.jiggle() } // Also OK
let clos = { () -> ()? in currentBottle?.jiggle() } // Still OK (Void and () are synonyms)

注意:如果让Swift为您推断正确的类型而不是显式强制使用它,它将为您解决此问题:

// Even better: type automatically inferred as ()->()? — also known as Void->Void?
let clos = { currentBottle?.jiggle() }

[编辑]

其他技巧:将可选链接直接分配给变量

您甚至可以将函数直接分配给变量,如下所示:

let clos2 = currentBottle?.jiggle // no parenthesis, we don't want to call the function, just refer to it

注意,类型clos2在此情况下(这是这里未明确指定,并且因此由夫特自动推断)是 Void->Void?
-即一个函数,返回任一nilVoid)如前面的情况下-但 (Void->Void)?,这是类型为“一种类型的 可选
功能Void->Void

这意味着它clos2本身就是“或者nil返回一个函数Void”。要使用它,您可以再次使用可选链接,就像这样:

clos2?()

nil如果clos2为本身nil(这可能是因为currentBottle本身为零),这将求值并且不执行任何操作……并执行闭包(因此为currentBottle!.jiggle()代码),Void如果clos2为非结果(则可能因为currentBottle自身为非零)而返回。

clos2?()本身的返回类型确实是Void?,因为它返回nil或Void。

Void和之间进行区分Void?似乎毫无意义(毕竟,在jiggle任何一种情况下该函数都不会返回任何内容),但是它可以让您执行强大的工作,例如Void?if语句中测试,以检查调用是否确实发生了(并且Void没有返回任何内容)或没有发生(并返回nil):

if clos2?() { println("The jiggle function got called after all!") }

[EDIT2]正如您(@matt)指出自己一样,另一种选择还有另一个主要区别:它currentBottle?.jiggle在表达式受到影响时进行评估clos2。所以,如果currentBottlenil在那个时候,clos2将是nil......即使currentBottle有一个非空值之后。

相反,clos它会影响闭包本身,并且仅在每次clos调用时都会评估可选链,因此它将评估nil是否currentBottle为nil…,但将评估为非nil,并且jiggle()如果我们clos()稍后再调用,则会进行调用。点currentBottle变成非零。



 类似资料:
  • 可选链(Optional Chaining)是一种可以请求和调用属性、方法和子脚本的过程,用于请求或调用的目标可能为nil。 可选链返回两个值: 如果目标有值,调用就会成功,返回该值 如果目标为nil,调用将返回nil 多次请求或调用可以被链接成一个链,如果任意一个节点为nil将导致整条链失效。 可选链可替代强制解析 通过在属性、方法、或下标脚本的可选值后面放一个问号(?),即可定义一个可选链。

  • 基本上,我试图建立一个报警应用程序,其中有一些预定义的日期和时间按钮。我一开始就尝试使用AlarmManager和广播接收器,但都不起作用。所以,我使用了alarmManager的前台服务,但仍然,当应用程序被摧毁时,警报不会发出。我是个新手。我试着在网上搜索,但我没有运气。希望这里有很多人来帮助我。提前谢了。 myservice.java AlarmReceiver.java

  • 问题内容: 并尝试应用他们的解决方案(以及至少1/2十二种其他实现),但没有一个起作用。 这是具有循环的函数: 这是正在写入我的消息的errorLogging函数(注意,我无法在同一JavaScript文件中“写入”消息,因为我需要[角度]向该文件中注入另一个引用,这会导致循环参考,代码将无法运行) 我还可以采用什么其他方法阻止它返回同步记录的最后一个“ id”(当它只是出现错误的第一个记录时)?

  • 问题内容: 我已经设置了版本4 的React。当我直接在浏览器中输入URL时,路由有效,但是当我单击链接时,URL在浏览器上发生了变化(例如http:// localhost:8080 / categories ),但是内容不会更新(但是如果我刷新,它会更新)。 以下是我的设置: 该 Routes.js 设置如下: 我在 Nav.js 中使用的链接如下: 该 App.js 如下: 问题答案: 包装

  • 我已经花了很多时间尝试按照一步一步的指南将这三个连接在一起,以便能够通过html表单将某些内容插入数据库。 以下是html代码: 下面是php代码: 下面是MySQL表: 数据库和表的图片,显示行和数据

  • 主要内容:为可选链和访问属性定义模型类,链的多级链接在可选的上查询,调用属性,下标和方法的过程叫作可选链。可选链接返回两个值 - 如果可选项包含值,则调用相关属性,方法和下标返回值。 如果可选项包含值,则所有相关属性,方法和下标返回。 由于对方法,属性和下标的多个查询组合在一起,因此对一个链的失败将影响整个链的结果为值。 可选链作为强制解包的替代方法 在带有的可选值后指定可选链,在可选值返回某些值时调用属性,方法或下标。 可选链 访问方法,属性和下