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

资料

相关推荐
songgeb13 小时前
iOS App支持设置RTL语言的实践
ios·swift·ui kit
2501_915106322 天前
KXApp 的 VS Code 真机调试:按下 Cmd+R 之后发生了什么
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
2601_955518182 天前
36. 跨语言:C/C++与Swift&Objective-C混合编程(一)
objective-c·swift·c/c++·混合编程·跨语言
东坡肘子3 天前
谁是 AI-relay App 的真正威胁 -- 肘子的 Swift 周报 #158
人工智能·swiftui·swift
叫Guava不是瓜娃4 天前
我用 Swift 写了个本地语音输入:按住说话,松开就是整理好的文字(开源)
swift
Yannik4 天前
iOS Swift Package Manager(SPM)私有组件完整实操
ios·swift
我就是不信5 天前
Swift 方法派发机制详解
开发语言·ios·swift
用户38034165882977 天前
八个私有 SPM 包撑起六款 App:分支当版本、钻石依赖,和一次谁都没报错的失效
ios·swift
健了个平_247 天前
【iOS】关于传统竖屏 UIKit 项目如何简单适配 iPhone Duo 的第一版
ios·app·swift
2501_915106328 天前
iOS开发之Xcode常用调试技巧总结
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程