iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Swift AsyncSequence — 代码实例详解
  • 184
分享到

Swift AsyncSequence — 代码实例详解

swift开发语言ios原力计划 2023-08-16 18:08:38 184人浏览 安东尼
摘要

文章目录 前言什么是 AsyncSequence?创建 AsyncSequence异步序列的迭代结论 前言 AsyncSequence 是并发性框架和 SE-298 提案的一部分。它的名字意味着它是一个提供异步、顺序和迭代访

前言

AsyncSequence并发框架SE-298 提案的一部分。它的名字意味着它是一个提供异步、顺序和迭代访问其元素的类型。换句话说:它是我们在 Swift 中熟悉的常规序列的一个异步变体。

就像你不会经常创建你的自定义序列一样,我不期望你经常创建一个自定义的 AsyncSequence 实现。然而,由于与 AsyncThrowingStream和AsyncStream 等类型一起使用,你很可能不得不与异步序列一起工作。因此,我将指导你使用 AsyncSequence 实例进行工作。

在这里插入图片描述

什么是 AsyncSequence?

AsyncSequence 是我们在Swift中熟悉的 Sequence 的一个异步变体。由于它的异步性,我们需要使用 await 关键字,因为我们要处理的是异步定义的方法。如果你没有使用过 async/await,我鼓励你阅读我的文章:Swift 中的async/await ——代码实例详解

值可以随着时间的推移而变得可用,这意味着一个 AsyncSequence 在你第一次使用它时可能不包含也可能包含一些,或者全部的值。

重要的是要理解 AsyncSequence 只是一个协议。它定义了如何访问值,但并不产生或包含值。AsyncSequence 协议的实现者提供了一个 AsyncIterator,并负责开发和潜在地存储值。

FunctionNote
contains(_ value: Element) async rethrows -> BoolRequires Equatable element
contains(where: (Element) async throws -> Bool) async rethrows -> BoolThe async on the closure allows optional async behavior, but does not require it
allSatisfy(_ predicate: (Element) async throws -> Bool) async rethrows -> Bool
first(where: (Element) async throws -> Bool) async rethrows -> Element?
min() async rethrows -> Element?Requires Comparable element
min(by: (Element, Element) async throws -> Bool) async rethrows -> Element?
max() async rethrows -> Element?Requires Comparable element
max(by: (Element, Element) async throws -> Bool) async rethrows -> Element?
reduce(_ initialResult: T, _ nextPartialResult: (T, Element) async throws -> T) async rethrows -> T
reduce(into initialResult: T, _ updateAccumulatingResult: (inout T, Element) async throws -> ()) async rethrows -> T

对于这些函数,我们首先定义一个符合 AsyncSequence 协议的类型。该名称是模仿现有的标准库“序列”类型,如 LazyDropWhileCollectionLazyMapSequence 。然后,我们在 AsyncSequence 的扩展中添加一个函数,该函数创建新类型(使用’ self ‘作为’ upstream ')并返回它。

Function
map(_ transform: (Element) async throws -> T) -> AsyncMapSequence
compactMap(_ transform: (Element) async throws -> T?) -> AsyncCompactMapSequence
flatMap(_ transform: (Element) async throws -> SegmentOfResult) async rethrows -> AsyncFlatMapSequence
drop(while: (Element) async throws -> Bool) async rethrows -> AsyncDropWhileSequence
dropFirst(_ n: Int) async rethrows -> AsyncDropFirstSequence
prefix(while: (Element) async throws -> Bool) async rethrows -> AsyncPrefixWhileSequence
prefix(_ n: Int) async rethrows -> AsyncPrefixSequence
filter(_ predicate: (Element) async throws -> Bool) async rethrows -> AsyncFilterSequence

创建 AsyncSequence

创建一个自定义的 AsyncSequence。

为了更好地理解 AsyncSequence 是如何工作的,我将演示一个实现实例。然而,在定义你的 AsyncSequence 的自定义实现时,你可能想用 AsyncStream 来代替,因为它的设置更方便。因此,这只是一个代码例子,以更好地理解 AsyncSequence 的工作原理。

下面的例子沿用了原始提案中的例子,实现了一个计数器。这些值可以立即使用,所以对异步序列没有太大的需求。然而,它确实展示了一个异步序列的基本结构:

struct Counter: AsyncSequence {    typealias Element = Int    let limit: Int    struct AsyncIterator : AsyncIteratorProtocol {        let limit: Int        var current = 1        mutating func next() async -> Int? {            guard !Task.isCancelled else {                return nil            }            guard current <= limit else {                return nil            }            let result = current            current += 1            return result        }    }    func makeAsyncIterator() -> AsyncIterator {        return AsyncIterator(howHigh: limit)    }}

如您所见,我们定义了一个实现 AsyncSequence 协议的 Counter 结构体。该协议要求我们返回一个自定义的 AsyncIterator,我们使用内部类型解决了这个问题。我们可以决定重写此示例以消除对内部类型的需求:

struct Counter: AsyncSequence, AsyncIteratorProtocol {    typealias Element = Int    let limit: Int    var current = 1    mutating func next() async -> Int? {        guard !Task.isCancelled else {            return nil        }        guard current <= limit else {            return nil        }        let result = current        current += 1        return result    }    func makeAsyncIterator() -> Counter {        self    }}

我们现在可以将 self 作为迭代器返回,并保持所有逻辑的集中。

注意,我们必须通过提供 typealias 来帮助编译器遵守 AsyncSequence 协议。

next() 方法负责对整体数值进行迭代。我们的例子归结为提供尽可能多的计数值,直到我们达到极限。我们通过对 Task.isCancelled 的检查来实现取消支持。

请添加图片描述

异步序列的迭代

现在我们知道了什么是 AsyncSequence 以及它是如何实现的,现在是时候开始迭代这些值了。

以上述例子为例,我们可以使用 Counter 开始迭代:

for await count in Counter(limit: 5) {    print(count)}print("Counter finished")// Prints:// 1// 2// 3// 4// 5// Counter finished

我们必须使用 await 关键字,因为我们可能会异步接收数值。一旦不再有预期的值,我们就退出for循环。异步序列的实现者可以通过在 next() 方法中返回 nil 来表示达到极限。在我们的例子中,一旦计数器达到配置的极限,或者迭代取消,我们就会达到这个预期:

mutating func next() async -> Int? {    guard !Task.isCancelled else {        return nil    }    guard current <= limit else {        return nil    }    let result = current    current += 1    return result}

许多常规的序列操作符也可用于异步序列。其结果是,我们可以以异步的方式执行映射和过滤等操作。

例如,我们可以只对偶数进行过滤:

for await count in Counter(limit: 5).filter({ $0 % 2 == 0 }) {    print(count)}print("Counter finished")// Prints: // 2// 4// Counter finished

或者我们可以在迭代之前将计数映射为一个 String

let counterStream = Counter(limit: 5)    .map { $0 % 2 == 0 ? "Even" : "Odd" }for await count in counterStream {    print(count)}print("Counter finished")// Prints:// Odd// Even// Odd// Even// Odd// Counter finished

我们甚至可以使用 AsyncSequence 而不使用for循环,通过使用 contains 等方法。

let contains = await Counter(limit: 5).contains(3)print(contains) // Prints: true

注意,上述方法是异步的,意味着它有可能无休止地等待一个值的存在,直到底层的 AsyncSequence 完成。

结论

AsyncSequence 是我们在Swift中熟悉的常规 Sequence 的异步替代品。就像你不会经常自己创建一个自定义 Sequence 一样,你也不太可能创建自定义的异步序列。

来源地址:https://blog.csdn.net/qq_36478920/article/details/130521833

--结束END--

本文标题: Swift AsyncSequence — 代码实例详解

本文链接: https://www.lsjlt.com/news/371936.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c语言怎么保证除完还是小数
    在 c 语言中,整数除法只能得到整数结果,要得到小数结果,需将操作数显式转换为浮点数:将一个操作数转换为浮点数,如 float result = num1 / (float)num2;将...
    99+
    2024-05-14
    c语言
  • c语言怎么让结尾不输出空行字符
    要阻止 c 语言程序结尾输出空行字符,可以使用以下方法:将 main 函数的返回值类型改为 void;在 main 函数中显式返回 0;调用 fflush(stdout) 函数刷新标准输...
    99+
    2024-05-14
    c语言
  • c语言怎么让结尾不输出空行数据
    在 c 语言中,可通过以下方法抑制 printf() 函数在程序结束时打印末尾空行:调用 fflush() 函数刷新缓冲区,立即输出所有数据;使用 setvbuf() 函数关闭缓冲,使数...
    99+
    2024-05-14
    c语言
  • c语言怎么让结尾无空行
    在 c 中去除结尾空行的方法:使用 fflush() 刷新缓冲区。使用 setvbuf() 将缓冲模式设置为 _ionbf。使用 printf 宏,它默认禁用缓冲。 如何在 C 语言中...
    99+
    2024-05-14
    c语言
  • c语言怎么输入实数赋值
    c语言中使用scanf()函数输入实数并赋值给变量:格式:scanf("%lf", &amp;variable);%lf是格式说明符,指定输入双精度浮点数;&...
    99+
    2024-05-14
    c语言
  • c语言怎么表达负数
    c语言中,负数以减号 (-) 表示,放在数字或变量前。负数运算规则包括:绝对值取正数;加正数或负数,结果取决于绝对值大小;乘或除以正数或负数,结果由符号奇偶性决定。负数的平方始终为正数,...
    99+
    2024-05-14
    c语言
  • c语言怎么输入Jac数列
    jacobi 数列的输入和生成方法分别有:1. 直接输入法:使用 scanf() 函数逐项输入数列。2. 递归生成法:使用递归公式生成数列,需初始化数列的前两项,然后按公式生成后续项。 ...
    99+
    2024-05-14
    c语言
  • c语言怎么把数组变成字符串
    在 c 语言中,将数组转换成字符串的方法包括:使用 sprintf() 将数组格式化为字符串。使用 strcpy() 将数组复制到字符串。使用 strncpy() 将指定长度的数组复制到...
    99+
    2024-05-14
    c语言
  • c语言怎么批量注释
    批量注释 c 语言代码的方法有:使用代码编辑器:使用快捷键或菜单命令自动添加 // 注释符号。使用注释工具:如 doxygen 和 cutter,批量添加行注释、块注释和文档注释。使用脚...
    99+
    2024-05-14
    python sublime c语言
  • c语言怎么把选中的全部注释
    c语言中注释选中内容可通过以下步骤实现:选中要注释的代码。根据使用的编辑器或ide,执行注释操作,例如在visual studio中右键单击并选择“注释所选内容”。添加注释内容。保存更改...
    99+
    2024-05-14
    sublime c语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作