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

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

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

ini 复制代码
let result2 = pairUp2(firstPeople: johnny, derek, secondPeople: kate, kevin)
相关推荐
Keya19 小时前
lipo 命令行指南
ios·xcode·swift
zhangmeng20 小时前
SwiftUI中如何实现子视图向父视图传递数据?
ios·swiftui·swift
Saafo20 小时前
迁移至 Swift Actors
ios·swift
杂雾无尘2 天前
告别构建错误, iOS 开发架构难题全面解析, 避免 CPU 架构陷阱
ios·swift·客户端
大熊猫侯佩2 天前
探秘 WWDC 25 全新 #Playground 宏:提升 Swift 开发效率的超级神器
xcode·swift·wwdc
移动端小伙伴3 天前
10.推送的扩展能力 — 打造安全的通知体验
swift
移动端小伙伴3 天前
推送的扩展能力 — 打造个性化的通知体验
swift
移动端小伙伴3 天前
远程推送(Remote Push Notification)
swift
移动端小伙伴3 天前
本地通知的精准控制三角:时间、位置、情境
swift
移动端小伙伴3 天前
本地通知内容深度解析 — 打造丰富的通知体验
swift