苹果组合框架:如何并行执行多个发布者并等待所有发布者完成?

2024-04-25

我正在发现组合。我编写了以“组合”方式发出 HTTP 请求的方法,例如:

func testRawDataTaskPublisher(for url: URL) -> AnyPublisher<Data, Error> {
    var request = URLRequest(url: url,
                             cachePolicy: .useProtocolCachePolicy,
                             timeoutInterval: 15)
    request.httpMethod = "GET"

    return urlSession.dataTaskPublisher(for: request)
        .tryMap {
            return $0.data
        }
        .eraseToAnyPublisher()
}

我想多次调用该方法并毕竟完成一项任务,例如:

let myURLs: [URL] = ...

for url in myURLs {
    let cancellable = testRawDataTaskPublisher(for: url)
        .sink(receiveCompletion: { _ in }) { data in
            // save the data...
        }
}

上面的代码不起作用,因为我必须将可取消项存储在属于该类的变量中。 第一个问题是:将许多(例如 1000)个可取消项存储在类似的内容中是一个好主意吗?Set<AnyCancellable>???不会造成内存泄漏吗?

var cancellables = Set<AnyCancellable>()

...

    let cancellable = ...

    cancellables.insert(cancellable) // ???

第二个问题是:当所有可取消的任务都完成后,如何开始任务?我在想类似的事情

class Test {
    var cancellables = Set<AnyCancellable>()

    func run() {
        // show a loader

        let cancellable = runDownloads()
            .receive(on: RunLoop.main)
            .sink(receiveCompletion: { _ in }) { _ in
                // hide the loader
            }

        cancellables.insert(cancellable)
    }

    func runDownloads() -> AnyPublisher<Bool, Error> {
        let myURLs: [URL] = ...

        return Future<Bool, Error> { promise in
            let numberOfURLs = myURLS.count
            var numberOfFinishedTasks = 0

            for url in myURLs {
                let cancellable = testRawDataTaskPublisher(for: url)
                    .sink(receiveCompletion: { _ in }) { data in
                        // save the data...
                        numberOfFinishedTasks += 1

                        if numberOfFinishedTasks >= numberOfURLs {
                            promise(.success(true))
                        }
                    }

                cancellables.insert(cancellable)
            }
        }.eraseToAnyPublisher()
    }

    func testRawDataTaskPublisher(for url: URL) -> AnyPublisher<Data, Error> {
        ...
    }
}

通常我会使用DispatchGroup,启动多个HTTP任务并在任务完成时使用通知,但我想知道如何使用Combine以现代方式编写它。


您可以通过创建发布者集合、应用flatMap运算符,然后collect等待所有发布者完成后再继续。这是一个可以在操场上运行的示例:

import Combine
import Foundation

func delayedPublisher<Value>(_ value: Value, delay after: Double) -> AnyPublisher<Value, Never> {
  let p = PassthroughSubject<Value, Never>()
  DispatchQueue.main.asyncAfter(deadline: .now() + after) {
    p.send(value)
    p.send(completion: .finished)
  }
  return p.eraseToAnyPublisher()
}

let myPublishers = [1,2,3]
  .map{ delayedPublisher($0, delay: 1 / Double($0)).print("\($0)").eraseToAnyPublisher() }

let cancel = myPublishers
  .publisher
  .flatMap { $0 }
  .collect()
  .sink { result in
    print("result:", result)
  }

这是输出:

1: receive subscription: (PassthroughSubject)
1: request unlimited
2: receive subscription: (PassthroughSubject)
2: request unlimited
3: receive subscription: (PassthroughSubject)
3: request unlimited
3: receive value: (3)
3: receive finished
2: receive value: (2)
2: receive finished
1: receive value: (1)
1: receive finished
result: [3, 2, 1]

请注意,发布者都立即启动(按原始顺序)。

The 1 / $0延迟导致第一个发布者需要最长的时间才能完成。请注意最后的值的顺序。由于第一个项目花费的时间最长,因此它是最后一个项目。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

苹果组合框架:如何并行执行多个发布者并等待所有发布者完成? 的相关文章

  • 带有 numberOfLines 和 lineBreakMode 的 UILabel

    我正在开发一个必须同时支持 iOS6 和 iOS7 的项目 我的问题是它在不同的系统上工作不同 我试图创建行数等于 2 的 UILabel 但是当我将其换行模式设置为 NSLineBreakByTruncatingTail 时 它的工作方式
  • 如何检测 OS X 上是否按下了某个键?

    我正在为 OSX 编写 Spritekit 游戏 如何检查当前是否按下某个键 考虑这个例子 some code this could be e g inside a game loop if is key w pressed move fo
  • 如何快速使用 CoreLocation?

    我尝试过将 CoreLocation 与我的 Swift 应用程序一起使用 但没有运气 我有以下非常简单的代码 我已经链接了 CoreLocation 库 import UIKit import CoreLocation UIApplica
  • 前导点的自动完成功能无法快速工作

    当我尝试在 swift 中使用 前导点语法 时 我没有得到任何自动完成建议 是否没有实现此自动完成功能 或者是我的 Xcode 版本 6 3 1 有问题 例如 当我尝试这样的事情时 let col UIColor whiteColor 在我
  • 无法在 Swift 3 / iOS 10 中触发 continueUserActivity

    注意 我已经弄清楚了大部分内容 请参阅最后的更新 还是有些迷茫 我正在尝试在 Swift 3 下的 Xc8b6 中实现 NSUserActivity 处理 但处理程序协议方法的方法签名遇到问题 在当前的文档中 该方法据说是 func app
  • SwiftUI withAnimation 完成回调

    我有一个基于某种状态的 swiftUI 动画 withAnimation linear duration 0 1 self someState newState 上述动画完成时是否会触发任何回调 如果有关于如何在 SwiftUI 中使用完成
  • iOS 12.1 上的 UITabBar 项目在返回导航上跳跃

    我有一个 iOS 应用程序UITabBarController在主屏幕上 导航到隐藏的详细信息屏幕UITabBarController有设置hidesBottomBarWhenPushed true 返回主屏幕时UITabBarContro
  • 生成具有给定分布的随机数

    看看这个问题 快速选择随机数的概率 https stackoverflow com questions 26092977 swift probability of random number being selected 最上面的答案建议使
  • 将属性类型作为参数传递

    有没有办法将属性作为参数传递给函数 class Car let doors Int 4 let price Int 1000 有没有办法将 Car 属性作为类型传递给函数 我想实现以下目标 func f1 car Car property
  • 在 Swift 中枚举多个具有相同值的情况

    在 C 中 你可以让你的枚举具有以下内容 typedef enum Bar A 0 B 0 C 1 Bar 在 Swift 中我想做等价的事情 然而 编译器抱怨它不是唯一的 我如何告诉它我希望两个案例具有相同的值 enum Bar Int
  • iOS 13.1 AVAudio 播放器崩溃

    当我跟踪问题时 我的应用程序在 iOS 13 1 上崩溃 然后发现应用程序崩溃是因为AVAudioPlayer 以下是我的播放器设置 if let wrongURL Bundle main url forResource wrongAudi
  • 如何测试包含应用程序是否授予“允许完全访问”权限?

    我正在开发一个键盘扩展项目 在应用程序代码的某些点 我需要测试用户是否已授予键盘扩展的 允许完全访问 权限 协议是我需要从应用程序端进行这些测试 并在此基础上让用户访问键盘设置或在未授予权限的情况下提醒他 问题是这里提供的方法如下 func
  • Swift 中构造泛型类型的扩展

    是否可以为专用 构造的泛型类型扩展泛型类 我想用一种方法来扩展 Int Arrays 来计算其元素之和 e g extension Array
  • Swift - 以编程方式刷新约束

    我的 VC 开头为stackView附有Align Bottom to Safe Area 我有 tabBar 但一开始是隐藏的tabBar isHidden true 稍后 当 tabBar 出现时 它会隐藏stackView 所以我需要
  • 仅为 UITableView 中的某个部分启用编辑模式

    我有一个tableView其中有一个可编辑的部分 如果我启用整个编辑tableView 其他单元格在编辑模式下不是selectable 所以我需要仅在特定部分启用编辑模式 以便其他单元格selectable 该部分是可编辑的 我需要设置编辑
  • CognitoIdentityCredentials 无权对资源执行:lambda:InvokeFunction

    我正在尝试从 iOS 客户端调用 lambda 函数 我的代码如下所示 要获取凭据 请在 appDelegate 中 func application application UIApplication didFinishLaunching
  • 下标的使用不明确

    该代码块以前可以工作 但现在不行了 我在纬度和经度变量上收到错误 下标 的使用不明确 这是怎么回事 这是因为 Swift 更新吗 func showPrecincts var urlBoundaries http www oklahomad
  • 如何为长时间运行的函数设置超时?

    我有一个带有一些代码的函数 可能需要很长时间才能完成 如果该功能花费的时间超过特定时间 我希望该功能停止继续 我怎样才能实现这个 我尝试了下面的解决方案 但它不会停止执行 override func viewDidLoad super vi
  • 将相机移动到点击的 SCNNode

    我在用着SceneKit and Swift尝试移动相机 使其 聚焦 在所选节点上 我知道我启用了 defaultCameraController 但我试图通过调整相机的位置dolly rotate and translateInCamer
  • 错误:将构建上传到 iTunes Connect 时,Swift 支持无效

    我正在提交 TestFlight 发行版的第一个版本 但收到以下错误 位码已关闭 其他答案似乎相当旧 所以我想我会在 2018 年重新询问 无效的 Swift 支持 文件 libswiftDarwin dylib libswiftMetal

随机推荐

  • 带有自定义离线页面的 Angular PWA

    在 Angular 8 应用程序中 我想添加一个自定义离线页面 只是一个简单的 html 文件 我已将我的应用程序设置为 PWA 使用 angular pwa并配置了一切 以便它至少在在线时顺利工作 然而 我很难为 PWA 用户提供更新 因
  • unsafePerformIO 和 FFI 库初始化

    我正在为 C 中的库创建一个 FFI 模块 该模块希望在执行其他操作之前调用一个一次性 不可重入的函数 这个调用是幂等的 但是有状态的 所以我可以在每个 Haskell 调用中调用它 但它很慢 并且由于不可重入 可能会导致冲突 那么现在是使
  • 允许用户在 Android 应用程序中插入图像

    我的问题是 如何创建 imageButton 允许用户从手机上传图像并将其作为图片配置文件插入应用程序中 例如 像 Whatsapp 一样 它允许用户从手机中选择图像并将其设置为图片配置文件 Thanks 我的 XML 文件
  • 为什么 Func 与 Func> 不明确?

    这个问题让我很困惑 所以我想我会在这里问 希望 C 大师可以向我解释一下 为什么这段代码会产生错误 class Program static void Main string args Foo X the error is on this
  • Laravel 5.3 存储和读取文件目录

    目前正在尝试处理文件 但很难弄清楚将它们放在哪里以及如何在列表中读回它们 我尝试过将一些测试文件放入 files array dir opendir asset files open the cwd also do an err check
  • 如何使用 pyspark 从 s3 存储桶读取 csv 文件

    我正在使用 Apache Spark 3 1 0 和 Python 3 9 6 我正在尝试从 AWS S3 存储桶读取 csv 文件 如下所示 spark SparkSession builder getOrCreate file s3 b
  • 不获取AudioListenerInterruptionEnd触发器

    我对 OpenAl 和 MPMoviePlayerController 的组合有疑问 我在 OpenAl 设置过程中注册了 AudioInterruptionLister 当我开始播放视频时 侦听器会收到 AudioListenerInte
  • 离子 3 角度 4 动画不起作用

    我有一个组件 我正在尝试为手风琴列表设置动画 我已经进行了所有更改 例如包括import BrowserModule from angular platform browser and import BrowserAnimationsMod
  • std::unordered_set 迭代器遍历的复杂性

    我最近玩了一个std unordered set http en cppreference com w cpp container unordered set 我怀疑我的 STL 版本会跟踪某些 FILO 数据结构 看起来像列表 中的非空存
  • Android JSON解析并存储到数据库

    我正在制作一个具有数据库的应用程序 现在我正在尝试从中解析数据值
  • Kafka Streams - 减少大型状态存储的内存占用

    我有一个拓扑 见下文 可以读取一个非常大的主题 每天超过十亿条消息 这个 Kafka Streams 应用程序的内存使用量相当高 我正在寻找一些关于如何减少状态存储占用空间的建议 更多详细信息如下 Note 我并不是想逃避国有商店 我只是认
  • 清除给定 iOS 应用程序的 cookie

    我的应用程序连接到服务器 并且基于 cookie 服务器将发出不同的响应 是否无法以编程方式清除cookie存储 以便服务器下次联系服务器时无法识别我的应用程序 据我所知 清除 Settings app 中的 Cookie 仅适用于 Saf
  • 如何用R中的频率表获得中位数? [复制]

    这个问题在这里已经有答案了 Problem 我改变了问题的表述 因为似乎缺乏清晰度 所以 我们有数千家医院 他们的患者年龄在 0 岁到 100 岁之间 对于每个年龄段 他们都有一定数量的患者 例如Hospital1 有 10 名 1 岁患者
  • 动态获取路由路径

    我最近将一些模板从 ERB 转换为 Haml 大多数情况下 它变得更干净 更好 但按钮定义开始变得糟糕 我想转换这个 link to t new default gt t helpers links new new intern path
  • Python ctypes 指向结构体指针的指针

    我在获取指向工作结构的指针时遇到问题 这是我抛出异常 ArgumentError 参数 1 预期 LP LP List 实例而不是指向 LP LP List 的指针 的代码 class List Structure fields head
  • 如何将额外参数传递给 R 中 do.call 的函数参数

    我想传递参数 stringsAsFactors FALSE to rbind in do call 但以下方法不起作用 data lt do call rbind strsplit readLines home jianfezhang ad
  • 用python计算逻辑回归

    我尝试计算逻辑回归 我有 csv 文件形式的数据 看起来像 node id second major gender major index year dorm high school student fac 0 0 2 257 2007 1
  • 为什么 ts-toolbelt 库使用“Oextendsunknown”表达式

    我正在研究 ts toolbelt 库的源代码 而我也经常遇到这样的表情O extends unknown 在我看来 它没有添加任何功能 所以我想知道 它是做什么用的 hidden export type UnionOf
  • Cypher - 匹配两个不同的可能路径并返回两者

    我有一个数据集 我在这里作为示例表示 http console neo4j org id 3dq78v http console neo4j org id 3dq78v 我想要做的是对于图表中的每个 Z 节点 该示例只有一个 但我有很多 我
  • 苹果组合框架:如何并行执行多个发布者并等待所有发布者完成?

    我正在发现组合 我编写了以 组合 方式发出 HTTP 请求的方法 例如 func testRawDataTaskPublisher for url URL gt AnyPublisher