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

资料

相关推荐
hxx2211 天前
iOS swift开发--- 加载PDF文件并显示内容
ios·pdf·swift
今天也想MK代码2 天前
基于ModelScope打造本地AI模型加速下载方案
ai·语言模型·swift·model·language model
袁代码2 天前
Swift 开发教程系列 - 第11章:内存管理和 ARC(Automatic Reference Counting)
开发语言·ios·swift·ios开发
袁代码3 天前
Swift 开发教程系列 - 第8章:协议与扩展
开发语言·ios·swift·ios开发
袁代码3 天前
Swift 开发教程系列 - 第9章:错误处理
开发语言·ios·swift·ios开发
iFlyCai3 天前
Swift中的Combine
开发语言·ios·swift·combine·swift combine
一丝晨光3 天前
Objective-C 1.0和2.0有什么区别?
java·开发语言·macos·c#·objective-c·swift·apple
新中地GIS开发老师4 天前
【GIS开发小课堂】高德地图+Three.js实现飞线、运动边界和炫酷标牌
开发语言·javascript·arcgis·前端框架·swift
袁代码4 天前
Swift 开发教程系列 - 第10章:泛型
开发语言·ios·swift·ios开发
袁代码4 天前
Swift 开发教程系列 - 第12章:协议与协议扩展
开发语言·ios·swift·ios开发