Swift中 Parameter Pack的妙用

什么是 parameter pack

  1. parameter pack 是Swift5.9中引入的一个新的类型,它是 Type parameter packs 和 value parameter packs的统称,它俩必须一起使用且长度相等
  2. 它允许我们编写可接受任意数量不同类型参数的泛型函数。
  3. 在SwiftUI中,一个View的子View最多有10个,有了parameter pack之后就可以突破这个限制

怎么使用 parameter pack

定义

看一下下面的代码。这个方法可以传入任意数量和类型的数组并返回每个数组的首元素组成的元组

swift 复制代码
func eachFirst<each T: Collection>(_ item: repeat each T) -> (repeat (each T).Element?) { 
    return (repeat (each item).first) 
}
  1. each T: Collection 是 type parameter pack语法,它表示每个参数必须遵循Collection协议
  2. repeat each T 是pack expansion语法,它将每个T类型展开成传入的对应值
  3. (repeat (each item).first) 是 value parameter pack语法,它表示重复每个参数的首元素,组成一个数组返回

使用

swift 复制代码
let numbers = [0, 1, 2] 
let names = ["Antoine", "Maaike", "Sep"] 
let firstValues = eachFirst(numbers, names) 
print(firstValues) // Optional(0), Optional("Antoine")

parameter pack 解决了什么问题

它让我们减少重载函数的代码,比如SwiftUI中ViewBuilder代码

它有10个重载函数,有了parameter pack之后就不需要这么多函数了,一个函数就搞定

static func buildBlock<each Content>(_ content: repeat each Content) -> TupleView<(repeat each Content)> where repeat each Content : View

妙用小招

不需要写多行代码就从一个结构中取多个值。

swift 复制代码
func valuesAt<T, each U>(
    _ subject: T, 
    keyPaths keyPath: repeat KeyPath<T, each U>
) -> (repeat each U) {
    (repeat (subject[keyPath: each keyPath]))
}

使用样例

swift 复制代码
let (number, user, head) = valuesAt(pullRequest, keyPaths: .number, .user.login, .head.sha)

任意的函数装饰器,减少高阶函数的重载次数

swift 复制代码
func decorateAround<each Argument, Return>(
    _ function: @escaping (repeat each Argument) -> Return,
    around: @escaping ((repeat each Argument) -> Return, repeat each Argument) -> Return
) -> (repeat each Argument) -> Return {
    { (argument: repeat each Argument) in
        around(function, repeat each argument)
    }
}

使用示例

swift 复制代码
let decoratedAddition: (Int, Int) -> Int = decorateAround(+) { add, a, b in
    let result = add(a, b)
    print("(a) + (b) = (result)")
    return result
}

print(decoratedAddition(1, 2))

实现通用的记忆体函数,减少耗时计算或加载

swift 复制代码
func memoize<each Argument: Hashable, Return>(
    _ function: @escaping (repeat each Argument) -> Return
) -> (repeat each Argument) -> Return {
    var storage = [AnyHashable: Return]()
    
    return { (argument: repeat each Argument) in
        var key = [AnyHashable]()
        repeat key.append(AnyHashable(each argument))
        
        if let result = storage[key] {
            return result
        } else {
            let result = function(repeat each argument)
            storage[key] = result
            return result
        }
    }
}

使用方式

swift 复制代码
let memoizedLoadImage = memoize(loadImage)

memoizedLoadImage(URL(filePath: "some-url"))
memoizedLoadImage(URL(filePath: "some-url"))

memoizedLoadImage(URL(filePath: "other-url"))

资料

相关推荐
Sirius Wu1 小时前
开源训练框架:MS-SWIFT详解
开发语言·人工智能·语言模型·开源·aigc·swift
从零开始学习人工智能1 小时前
USDT区块链转账 vs SWIFT跨境转账:技术逻辑与场景博弈的深度拆解
开发语言·ssh·swift
RickeyBoy10 小时前
Swift6 @retroactive:Swift 的重复协议遵循陷阱
swiftui·swift
东坡肘子3 天前
Homebrew 5.0:并行加速、MCP 加持,与 Intel 的最后倒计时 -- 肘子的 Swift 周报 #0111
rust·swiftui·swift
RickeyBoy3 天前
Swift 6 迁移常见 crash: _dispatch_assert_queue_fail
swiftui·swift
3***49963 天前
Swift Experience
开发语言·ios·swift
HarderCoder4 天前
Swift 一个小型游戏对象模型渐进式设计(四)——类型擦除与 Existential:当泛型遇见动态派发
swift
HarderCoder4 天前
Swift 一个小型游戏对象模型渐进式设计(五)——Swift 并发世界:把 Attackable 搬进 actor
swift
HarderCoder4 天前
Swift 一个小型游戏对象模型渐进式设计(三)——把能力再抽象一层,写一套“伤害计算器”框架
swift
HarderCoder4 天前
Swift 一个小型游戏对象模型渐进式设计(二)——协议与默认实现:如何写出不用继承的多态
swift