Swift 5.9 新特性:值和类型参数包

前言

在 Swift5.9 的版本中,经过 Apple 进行一系列的改动,可以允许开发者使用可变泛型参数。

上述改动解决了 Swift 中的一个很重要问题,就是泛型函数需要特定数量的类型参数。虽然这些函数仍然可以接受可变参数,但它们最终仍然必须使用相同的类型。

比如下面的例子,假设我们三个不同的结构体用来代表程序员不同的角色:

arduino 复制代码
struct FrontEndDev {
    var name: String
}

struct BackEndDev {
    var name: String
}

struct FullStackDev {
    var name: String
}

当然,在实际需求中这些结构体会有更多的属性用来实现需求,但此处仅是举例,所以只给结构体一个 name 的属性。

接着我们为每个结构体创建实例:

ini 复制代码
let johnny = FrontEndDev(name: "Johnny Appleseed")
let jess = FrontEndDev(name: "Jessica Appleseed")
let kate = BackEndDev(name: "Kate Bell")
let kevin = BackEndDev(name: "Kevin Bell")

let derek = FullStackDev(name: "Derek Derekson")

然后,当涉及到实际工作时,我们可以使用一个简单的函数将开发人员匹配在一起,如下所示:

swift 复制代码
func pairUp1<T, U>(firstPeople: T..., secondPeople: U...) -> ([(T, U)]) {
    assert(firstPeople.count == secondPeople.count, "You must provide equal numbers of people to pair.")
    var result = [(T, U)]()

    for i in 0..<firstPeople.count {
        result.append((firstPeople[i], secondPeople[i]))
    }

    return result
}

它使用两个可变参数来接收一组第一个人和一组第二个人,然后将它们作为数组返回。我们现在可以使用它来创建一个组程序员,改组需要处理某些前端和后端的工作。

ini 复制代码
let result1 = pairUp1(firstPeople: johnny, jess, secondPeople: kate, kevin)

到目前为止,都是按照 Swift 5.9 之前的版本去写的代码。但有趣的是: Derek 是一名全栈开发人员,因此既可以担任后端开发人员,也可以担任前端开发人员。然而,如果我们尝试使用johnny, derek作为第一个参数,那么 Swift 编译器将会报错。因为它需要第一个人和第二个人的类型是相同的。

我们可以使用 any 关键字来抹除所有的类型信息,从而解决这个问题。但这样就失去了很多可以利用的 Swift 特性,我们可以用参数包来更优雅的解决这个问题。

参数包

乍一开始看到这个语法可能会有点懵,下面先写出完整代码,后面再一点点分解它:

sql 复制代码
func pairUp2<each T, each U>(firstPeople: repeat each T, secondPeople: repeat each U) -> (repeat (first: each T, second: each U)) {
    return (repeat (each firstPeople, each secondPeople))
}

让我们分解成四部分来理解它:

  • <each T, each U> 创建了两个类型参数包, T 和 U
  • repeat each T 是一个包扩展,它将参数包扩展为实际值 - 它相当于 T...,但避免了与 ... 用作运算符造成混淆
  • 返回类型意味着我们要发回配对程序员的元组,T 和 U 各一个
  • return 关键字的作用:它使用包扩展表达式从 T 中获取一个值,从 U 中获取一个值,然后将它们组合在一起形成返回值

需要注意的是,返回类型会自动确保我们的 T 和 U 类型具有相同的形状------它们内部具有相同数量的元素。因此,如果我们试图传入两组不同大小的数据,Swift 会编译报错,而不是像在第一个函数中那样使用assert()。

下面是新函数的调用示例:

ini 复制代码
let result2 = pairUp2(firstPeople: johnny, derek, secondPeople: kate, kevin)
相关推荐
东坡肘子1 天前
参与学生移动应用大赛有感 -- 肘子的 Swift 周报 #161
人工智能·swiftui·swift
songgeb6 天前
YYImage Bug:一行之差,正常 JPEG 如何在 iOS 被读成条纹
ios·swift
fthux6 天前
Tick Rest,一个休息提醒工具的自我修养
macos·开源·swift
Fatbobman(东坡肘子)6 天前
快速消失的硬盘容量 -- 肘子的 Swift 周报 #160
开发语言·人工智能·redis·ios·swiftui·iphone·swift
chaoahyl7 天前
WaterDiary 喝水记录 App 实战(2)· 实现喝水首页与本地保存
swift
茶底世界之下8 天前
iPhone Duo 适配实战,Awaking 踩过的 8 个坑
ios·swiftui·swift
xbzb8 天前
Swift 对象存储建环实验 + Ceilometer 计量:两个收尾服务
swift·ring·实验·ceilometer·象存储·建环
2501_916008898 天前
iOS App 图标、启动屏和多语言搭配 方法,上架前使用KXBuild一次做好 App 图标
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
2501_915918418 天前
iOS 推送通知怎么实现,从 APNs p8 密钥到 iOS 真机收到第一条推送
vscode·ios·objective-c·个人开发·swift·敏捷流程
东坡肘子8 天前
快速消失的硬盘容量 -- 肘子的 Swift 周报 #160
人工智能·swiftui·swift