CollectionConcurrencyKit

欢迎使用 CollectionConcurrencyKit,这是一个轻量级的 Swift 包,它为所有符合 Sequence 协议的 Swift 集合添加了异步和并发版本的标准 mapflatMapcompactMapforEach API。 这包括内置类型,如 ArraySetDictionary,以及任何符合该协议的自定义集合。

CollectionConcurrencyKit 可用于以充分利用 Swift 内置并发系统的方式实现高性能数据处理和算法。 它经过了大量的单元测试,拥有完整的文档,并且已在生产环境中用于生成 swiftbysundell.com

异步迭代

CollectionConcurrencyKit 的 API 的异步变体使您能够在各种映射和 forEach 迭代中调用标记为 async 的函数,同时仍然保持完全可预测的顺序执行。

例如,以下是我们如何使用 asyncMap 从 URL 集合下载一系列 HTML 字符串

let urls = [
    URL(string: "https://apple.com")!,
    URL(string: "https://swiftlang.cn")!,
    URL(string: "https://swiftbysundell.com")!
]

let htmlStrings = try await urls.asyncMap { url -> String in
    let (data, _) = try await URLSession.shared.data(from: url)
    return String(decoding: data, as: UTF8.self)
}

以下是我们如何使用 asyncCompactMap 通过返回一个可选值而不是抛出错误来忽略任何下载失败

let htmlStrings = await urls.asyncCompactMap { url -> String? in
    do {
        let (data, _) = try await URLSession.shared.data(from: url)
        return String(decoding: data, as: UTF8.self)
    } catch {
        return nil
    }
}

CollectionConcurrencyKit 的每个 API 都提供抛出和非抛出变体,因此由于上面对 asyncCompactMap 的调用不会抛出,因此我们在调用它时无需使用 try

并发

CollectionConcurrencyKit 还包括 forEachmapflatMapcompactMap 的并发变体,它们并行执行迭代,同时在生成结果时仍然保持可预测的顺序。

例如,由于我们的上述 HTML 下载代码由完全独立的操作组成,我们可以使用 concurrentMap 并行执行每个操作,从而显着提高速度

let htmlStrings = try await urls.concurrentMap { url -> String in
    let (data, _) = try await URLSession.shared.data(from: url)
    return String(decoding: data, as: UTF8.self)
}

如果我们想并行化基于 asyncCompactMap 的上述代码变体,那么我们可以使用 concurrentCompactMap 来做到这一点

let htmlStrings = await urls.concurrentCompactMap { url -> String? in
    do {
        let (data, _) = try await URLSession.shared.data(from: url)
        return String(decoding: data, as: UTF8.self)
    } catch {
        return nil
    }
}

无论我们选择 CollectionConcurrencyKit 的 API 的异步版本还是并发版本,返回结果的顺序始终保证与调用标准库的非异步版本 API 时完全相同。 因此,htmlStrings 数组的顺序在上述所有四个代码示例中都是相同的(忽略 compactMap 变体产生的任何 nil 值)。

包含哪些 API?

CollectionConcurrencyKit 将以下 API 添加到所有符合 Sequence 协议的 Swift 集合中

包括上述所有 API 的抛出和非抛出版本。 要了解有关 mapflatMapcompactMap 的更多信息,请查看本文

系统要求

CollectionConcurrencyKit 适用于所有支持 Swift 并发系统的操作系统版本,目前包括 iOS 15、macOS 12、watchOS 8 和 tvOS 15,以及 Linux(当使用 5.5 或更高版本的 Swift 工具链时)。

Apple 目前正在努力为 Swift 的并发系统添加向后兼容性,一旦该功能完全可用(目前在测试版中,作为 Xcode 13.2 的一部分),CollectionConcurrencyKit 也将更新以支持更早的 OS 版本。

安装

CollectionConcurrencyKit 是使用 Swift Package Manager 分发的。 要在另一个 Swift 包中安装它,请在您的 Package.swift 清单中将其添加为依赖项

let package = Package(
    ...
    dependencies: [
        .package(url: "https://github.com/JohnSundell/CollectionConcurrencyKit.git", from: "0.1.0")
    ],
    ...
)

如果您想在 iOS、macOS、watchOS 或 tvOS 应用程序中使用 CollectionConcurrencyKit,请使用 Xcode 的 File > Add Packages... 菜单命令将其添加到您的项目中。

然后在任何你想使用它的地方导入 CollectionConcurrencyKit

import CollectionConcurrencyKit

有关如何使用 Swift Package Manager 的更多信息,请查看 本文,或 其官方文档

支持和贡献

CollectionConcurrencyKit 已根据非常宽松的 MIT 许可证 免费提供给整个 Swift 社区,但请注意,它不附带任何官方支持渠道,例如 GitHub 问题或基于 Twitter/电子邮件的支持。 因此,在您开始在您的项目中使用 CollectionConcurrencyKit 之前,强烈建议您花一些时间熟悉 它的实现,以防您遇到任何需要调试的问题。

如果您发现了一个错误、文档拼写错误,或者想要提出性能改进建议,请随时 打开一个 Pull Request(即使它只包含一个重现给定问题的单元测试)。 欢迎各种修复和调整,但 CollectionConcurrencyKit 旨在成为一个非常小巧且专注的库,因此它被认为是或多或少功能完整的。 因此,如果您想向该库添加任何重要的新功能,建议您 fork 它,这将允许您扩展和自定义它以满足您的需求。

希望您喜欢使用 CollectionConcurrencyKit!