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 向所有符合 Sequence 协议的 Swift 集合添加了以下 API

以上所有 API 都包含抛出和非抛出版本。要了解有关 mapflatMapcompactMap 的更多信息,请查看这篇文章

系统要求

CollectionConcurrencyKit 在所有支持 Swift 并发系统的操作系统版本上运行,包括 iOS 13+、macOS 10.15+、watchOS 6+ 和 tvOS 13+,以及 Linux(当使用 5.5 或更高版本的 Swift 工具链时)。请注意,在 Apple 平台上使用 CollectionConcurrencyKit 时,您需要使用 Xcode 13.2 或更高版本。

安装

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 issues 或基于 Twitter/电子邮件的支持。因此,在您开始在您的任何项目中使用 CollectionConcurrencyKit 之前,强烈建议您花一些时间熟悉 它的实现,以防您遇到任何需要调试的问题。

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

希望您喜欢使用 CollectionConcurrencyKit!