IOS Swift 从入门到精通:闭包第二部分,高级闭包

2024-06-23 06:52

本文主要是介绍IOS Swift 从入门到精通:闭包第二部分,高级闭包,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 当闭包接受参数时使用闭包作为参数
  • 当闭包返回值时使用闭包作为参数
  • 简写参数名称
  • 高级闭包: 具有多个参数的闭包
  • 高级闭包:从函数返回闭包
  • 高级闭包:捕获值
  • 总结

当闭包接受参数时使用闭包作为参数

这是闭包开始变得有点像线路噪声的地方:传递给函数的闭包也可以接受它自己的参数。

我们一直使用() -> Void它来表示“不接受任何参数并且不返回任何内容”,但是您可以继续填充()闭包应该接受的任何参数的类型。

为了证明这一点,我们可以编写一个travel()接受闭包作为其唯一参数的函数,并且该闭包又接受一个字符串:

func travel(action: (String) -> Void) {print("I'm getting ready to go.")action("London")print("I arrived!")
}

现在,当我们travel()使用尾随闭包语法调用时,我们的闭包代码需要接受一个字符串:

 travel { (place: String) inprint("I'm going to \(place) in my car") }

当闭包返回值时使用闭包作为参数

我们一直使用() -> Void它来表示“不接受任何参数并且不返回任何内容”,但是您可以Void用任何类型的数据替换它以强制闭包返回一个值。

为了证明这一点,我们可以编写一个travel()接受闭包作为其唯一参数的函数,而该闭包又接受一个字符串并返回一个字符串:

func travel(action: (String) -> String) {print("I'm getting ready to go.")let description = action("London")print(description)print("I arrived!")
}

现在,当我们travel()使用尾随闭包语法调用时,我们的闭包代码需要接受一个字符串并返回一个字符串:

travel { (place: String) -> String inreturn "I'm going to \(place) in my car"
}

简写参数名称

我们刚刚创建了一个travel()函数。它接受一个参数,这是一个闭包,它本身接受一个参数并返回一个字符串。然后该闭包在两次调用之间运行print()。

代码如下:

func travel(action: (String) -> String) {print("I'm getting ready to go.")let description = action("London")print(description)print("I arrived!")
}

我们可以travel()使用如下方法调用:

travel { (place: String) -> String inreturn "I'm going to \(place) in my car"
}

但是,Swift知道该闭包的参数必须是字符串,因此我们可以将其删除:

travel { place -> String inreturn "I'm going to \(place) in my car"
}

它还知道闭包必须返回一个字符串,所以我们可以删除它:

travel { place inreturn "I'm going to \(place) in my car"
}

由于闭包只有一行代码,并且必须是返回值的代码,所以 Swiftreturn也允许我们删除关键字:

travel { place in"I'm going to \(place) in my car"
}

Swift 有一个简写语法,可以让你写得更简洁。我们可以让 Swift 自动为闭包的参数提供名称,而不是直接书写place in。这些参数以美元符号命名,然后是一个从 0 开始的数字。

travel {"I'm going to \($0) in my car"
}

高级闭包: 具有多个参数的闭包

为了确保一切都清楚,我们将使用两个参数编写另一个闭包示例。

这次我们的travel()函数需要一个闭包来指定某人要去的地方以及他们要行驶的速度。这意味着我们需要使用(String, Int) -> String参数的类型:

func travel(action: (String, Int) -> String) {print("I'm getting ready to go.")let description = action("London", 60)print(description)print("I arrived!")
}

我们将使用尾随闭包和简写闭包参数名称来调用它。因为这接受两个参数,所以我们将同时获取$0和$1:

travel {"I'm going to \($0) at \($1) miles per hour."
}

有些人不喜欢使用简写参数名称,$0因为它可能会造成混淆,但这没关系 - 只要对您来说最有效就行。

高级闭包:从函数返回闭包

就像你可以将闭包传递给函数一样,你也可以从函数获取返回的闭包。

这个语法首先有点令人困惑,因为它使用了->两次:一次用于指定函数的返回值,第二次用于指定闭包的返回值。

为了尝试这一点,我们将编写一个travel()不接受任何参数但返回闭包的函数。返回的闭包必须使用字符串调用,并且不会返回任何内容。

在 Swift 中它看起来是这样的:

func travel() -> (String) -> Void {return {print("I'm going to \($0)")}
}

我们现在可以调用travel()来取回该闭包,然后将其作为函数调用:

let result = travel()
result("London")

从技术上讲,直接调用返回值是允许的(尽管并不推荐!)travel():

let result2 = travel()("London")

高级闭包:捕获值

如果在闭包中使用任何外部值,Swift会捕获它们 - 将它们与闭包一起存储,这样即使它们不再存在也可以对其进行修改。

现在我们有一个travel()返回闭包的函数,返回的闭包接受一个字符串作为其唯一参数并且不返回任何内容:

func travel() -> (String) -> Void {return {print("I'm going to \($0)")}
}

我们可以调用travel()来取回闭包,然后自由地调用该闭包:

let result = travel()
result("London")

如果我们创建在travel()闭包内部使用的值,就会发生闭包捕获。例如,我们可能想要跟踪返回的闭包被调用的频率:

func travel() -> (String) -> Void {var counter = 1return {print("\(counter). I'm going to \($0)")counter += 1}
}

即使该counter变量是在内部创建的travel(),它也会被闭包捕获,因此它仍然会对该闭包保持有效。

因此,如果我们result(“London”)多次调用,计数器就会不断增加:

result("London")
result("London")
result("London")

总结

  • 您可以将闭包分配给变量,然后稍后调用它们。
  • 闭包可以接受参数并返回值,就像常规函数一样。
  • 您可以将闭包作为参数传递给函数,并且这些闭包可以具有自己的参数和返回值。
  • 如果函数的最后一个参数是闭包,则可以使用尾随闭包语法。
  • $0Swift 自动提供像和 这样的简写参数名称$1,但并不是每个人都使用它们。
  • 如果在闭包内部使用外部值,它们将被捕获,以便闭包稍后可以引用它们。

这篇关于IOS Swift 从入门到精通:闭包第二部分,高级闭包的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1086437

相关文章

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

Java中的for循环高级用法

《Java中的for循环高级用法》本文系统解析Java中传统、增强型for循环、StreamAPI及并行流的实现原理与性能差异,并通过大量代码示例展示实际开发中的最佳实践,感兴趣的朋友一起看看吧... 目录前言一、基础篇:传统for循环1.1 标准语法结构1.2 典型应用场景二、进阶篇:增强型for循环2.

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

使用Python进行GRPC和Dubbo协议的高级测试

《使用Python进行GRPC和Dubbo协议的高级测试》GRPC(GoogleRemoteProcedureCall)是一种高性能、开源的远程过程调用(RPC)框架,Dubbo是一种高性能的分布式服... 目录01 GRPC测试安装gRPC编写.proto文件实现服务02 Dubbo测试1. 安装Dubb

Redis 配置文件使用建议redis.conf 从入门到实战

《Redis配置文件使用建议redis.conf从入门到实战》Redis配置方式包括配置文件、命令行参数、运行时CONFIG命令,支持动态修改参数及持久化,常用项涉及端口、绑定、内存策略等,版本8... 目录一、Redis.conf 是什么?二、命令行方式传参(适用于测试)三、运行时动态修改配置(不重启服务

Oracle 数据库数据操作如何精通 INSERT, UPDATE, DELETE

《Oracle数据库数据操作如何精通INSERT,UPDATE,DELETE》在Oracle数据库中,对表内数据进行增加、修改和删除操作是通过数据操作语言来完成的,下面给大家介绍Oracle数... 目录思维导图一、插入数据 (INSERT)1.1 插入单行数据,指定所有列的值语法:1.2 插入单行数据,指

MySQL DQL从入门到精通

《MySQLDQL从入门到精通》通过DQL,我们可以从数据库中检索出所需的数据,进行各种复杂的数据分析和处理,本文将深入探讨MySQLDQL的各个方面,帮助你全面掌握这一重要技能,感兴趣的朋友跟随小... 目录一、DQL 基础:SELECT 语句入门二、数据过滤:WHERE 子句的使用三、结果排序:ORDE