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_9159184110 分钟前
Swift IDE 有哪些?按平台和需求选择Swift 开发工具
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
懋学的前端攻城狮21 小时前
把 SwiftUI List 换成 NSTableView:一次目录树卡顿的排查记录
macos·swiftui·swift
2501_915106321 天前
Swift 开发环境搭建指南:三条路径按目标对号入座
开发语言·vscode·ios·objective-c·个人开发·swift·敏捷流程
东坡肘子2 天前
AI 想放弃了,人没有 -- 肘子的 Swift 周报 #150
人工智能·swiftui·swift
冯汉栩3 天前
Swift Control RollingCountdownView(动画倒计时)
开发语言·ios·swift
末代iOS程序员华仔3 天前
iOS 语聊直播/聊天APP4.3条例被拒解决
flutter·ios·swift
denggun123453 天前
Python两套原生信号量与swift对比
开发语言·python·swift
2601_965798474 天前
Build a Fast, High-Ranking Restaurant Website with Rolanda Theme
开发语言·ios·swift
00后程序员张5 天前
iOS 开发全流程需要哪些工具?编码、调试、构建、发布阶段选择
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
weixin_531670896 天前
Interlude起来:久坐提醒软件为什么需要登录?有没有完全本地运行的Mac休息提醒软件?
人工智能·macos·swift