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"))

资料

相关推荐
2501_915921431 天前
在没有源码的前提下,怎么对 Swift 做混淆,IPA 混淆
android·开发语言·ios·小程序·uni-app·iphone·swift
00后程序员张1 天前
对比 Ipa Guard 与 Swift Shield 在 iOS 应用安全处理中的使用差异
android·开发语言·ios·小程序·uni-app·iphone·swift
大熊猫侯佩2 天前
星际穿越:SwiftUI 如何让 ForEach 遍历异构数据(Heterogeneous)集合
swiftui·swift·遍历·foreach·any·异构集合·heterogeneous
hjs_deeplearning2 天前
认知篇#15:ms-swift微调中gradient_accumulation_steps和warmup_ratio等参数的意义与设置
开发语言·人工智能·机器学习·swift·vlm
墨瑾轩2 天前
C# PictureBox:5个技巧,从“普通控件“到“图像大师“的蜕变!
开发语言·c#·swift
@大迁世界6 天前
Swift、Flutter 还是 React Native:2026 年你该学哪个
开发语言·flutter·react native·ios·swift
Swift社区7 天前
在Swift中实现允许重复的O(1)随机集合
开发语言·ios·swift
初级代码游戏8 天前
iOS开发 SwiftUI 8:NavigationView 导航
ios·swiftui·swift
虹少侠8 天前
基于 WebKit 构建 macOS 多浮窗视频播放的技术实践(含完整产品落地)
前端·macos·swift·webkit
开开心心_Every10 天前
文件数量统计工具:支持多层文件夹数量统计
游戏·微信·pdf·excel·语音识别·swift·lisp