Swift中的闭包

在过去的九个月里,我一直在学习Swift。 说我正在爆炸是轻描淡写。 但是,每当我要举行快速聚会时,街上都会有一辆警车在等着将其关闭。 噢,封锁,谁伤害了你? 所以我最终决定学习闭包,并考虑记录我的奋斗学习和最后的阿哈时刻 。 这些大多数都是我从不同来源学到的东西,但发现自己希望自己在一个地方找到。 这些内容包括但不限于Bob the Dev的博客,快速的文档以及有关Medium的惊人文章。

为什么叫名字?

闭包可以从定义它们的上下文中捕获和存储对任何常量和变量的引用。 这被称为关闭它们,因此被称为closures。

您看起来很熟悉,我以前在哪里见过您?

闭包由于其干净且经过优化的语法而处在许多地方。 您可能在什么时候遇到过他们;

  • 使用动画; 这是因为某些功能是异步执行的。 这是使用escaping闭包的绝佳机会。
  • 从第三方API获取数据; 这也是使用escaping闭包的另一个绝佳机会。
  • 在视图控制器之间传递数据

Swift的许多内置函数都需要关闭。 这是一个;

闭包函数

Apple将闭包定义为传递的自包含功能块。 在我们过于技术化之前,我们可以了解如何将函数转换为闭包。

这是一个简单的函数,用于查找必须学习闭包的时间。 它需要两个参数, daysname然后返回一个字符串,告诉我我还剩下多少天。 优雅吧? 😃

将其转换为闭包;

  • 除去花括号

当然,如果您尝试按原样运行上述代码段,则会收到错误消息。 这是介于闭包和函数之间的东西,也许我们可以称其为乐趣。 没有? 好的! 😄

  • 在参数列表和正文之间(即在Stringreturn之间)添加关键字

这仍然有一个错误。

  • 尽管这是一个有很多观点和观点的有争议的声明,但闭包本质上是无头函数。 因此,我们取出头部😈。 在这种情况下,头部很func learnClosures

还是不运行?

  • 用花括号将其包围

most。 这是最冗长形式的所谓闭包表达式。 稍后我们将看到,您可以将其精简为一行。

  • 现在,我们基本上已经声明了一个闭合,但是没有一种调用它的方法。 解? 我们将其分配给变量。 这实际上是可能的,因为闭包被称为一流。 对于函数也是如此。

在这里,我们有一个完整的闭包形式。

定义闭包

与函数一样,闭包有多种形式。

  • 不带任何参数且不返回任何内容的闭包

在Swift中, void()相同。 通常,必须为闭包指定返回 类型 。 上面的闭包不接受任何参数什么也不返回

我们可以简化它,以减少冗长 ;

我们做了什么?

  1. 我们从声明中取出类型 ,这是因为闭包可以从上下文中推断出类型。 然后,我们继续删除返回类型。 这就是为什么闭包表达式可以从context推断参数并返回类型的原因
  2. 我们还删除了in关键字,这是因为除去参数后,我们没有要与主体分开
  • 接受参数且不返回任何值的闭包

闭包接受一个参数 string ,不返回任何内容。

同样,我们可以将其简化为

我们做了什么?

  1. 我们删除参数名称,并使用Swift自动生成的参数名称
  2. 在Swift中为每个参数分配了一个名称。 假设我们有三个参数,我们称它们为(a,b,c)。 Swift会分配它们($ 0,$ 1,$ 2)。
  3. 这是闭包表达式的另一种处理能力,称为赋值速记参数名称。
  • 接受参数并返回内容的闭包

闭包接受一个参数 oneString 类型的 string 返回一个字符串。

您知道练习,不是没有人有时间键入这种冗长的闭包!!!

调用闭包

您可以在函数中使用闭包

从函数返回闭包

我们将看两个例子;

  1. 使用闭包表达式

2.使用嵌套函数 ; 如我们所见,嵌套函数是闭包的特殊情况

注意事项

关闭有3种主要形式

  • 全局功能 ; 这些是闭包,其名称无法捕获其周围的值
  • 嵌套函数 s; 具有捕获其封闭函数值的名称的闭包
  • 闭包表达式 ; 未命名的闭包,捕获其周围上下文的值

瓶盖的特点

  • 像函数一样,闭包参数是常量,除非标记为n n-out 否则不能修改

但是,就像在函数中一样,您可以将其标记为in-out并设法解决该错误。

漂亮又漂亮
  • 闭包捕获周围环境的变量

在这里,我们将参考嵌套函数示例。

通过上面的代码片段,可以证明需要关闭。 在第一个示例中,当我们使用嵌套函数nee闭包时,它将捕获variable a的值,并在定义范围结束后继续使用它。 这就是为什么每当我们调用它时,它就已经有一个值并从那里递增。

但是,使用简单的函数会丢失变量的值,因此每次调用函数时都要重新开始。

  • 封闭件是参考类型

风味/功能类型

  • 尾随封口

当您将闭包用作函数中的最后一个参数并且太长而不能用作内联闭包时,将使用这些函数。

逃逸关闭

转义的闭包前面有@转义,而非转义的闭包则没有。 definition定义不够好? 让我通过解释他们的生命周期再做一个尝试。

逃逸的闭包中 ,生命周期如下所示:

  1. 在函数参数中传递闭包
  2. 做一些功能
  3. 返回编译器
  4. 异步运行闭包

这意味着闭包的寿命超过了函数,即在函数返回后调用它。 一个例子是完成处理程序 ; 一个仅在完成某些任务后才运行的闭包。

用例;

转义闭包用于异步编程中。 如果您在本真棒教程中不了解多线程,则可能需要看看它。 在多线程中,我们使用多个队列。 使用转义的闭包时,队列将保留闭包,并且仅在队列完成后才运行它。

访问全局变量时,也使用转义闭包。 这是因为变量比闭包有效。

在以上代码段中,我们有一个用于修改全局变量的闭包。 它应该可以访问不在其调用函数范围内的此变量,因此需要转义。

在Swift3之前,除非明确声明为noescape,否则所有闭包都在转义 但是,由于内存管理的原因,您现在必须声明何时希望关闭转义符。

非逃逸关闭的生命周期

  1. 在函数论证中通过关闭
  2. 做一些工作
  3. 运行关闭
  4. 返回编译器

正如您将看到的,无转义的闭包不会超过它的调用函数。

结论

  1. 到目前为止,我在做动画,使用多线程和从外部API获取数据时都使用了闭包。 我期待使用它们来自定义视图,例如按钮,在使用MVVM时在函数中编写更简洁的代码,最重要的是在绑定组件中编写代码

2.太好了! 我们了解有关闭包的所有这些知识, 下一步

  • 在学习闭包时,我将内存管理视为我们使用转义闭包的主要原因。 我建议使用Apple文档,以了解更多有关该文档的信息。
  • 就个人而言,我发现闭包并不是自然而然的,我想对于其他许多开发人员来说,闭包也是一样的。 我建议您养成阅读其他经验丰富的开发人员代码的习惯,以了解他们如何使用闭包。
  • 看看内置的带有关闭功能的Swift函数会很有帮助。

3.您能帮忙吗? 我故意没有说明闭包是引用类型 。 这是因为说实话,我对这一点不太了解 。 您是封闭 忍者吗? 你能帮忙吗? 我希望在同一the的评论中进行交谈。