【问题标题】:Combine pipeline to download image from Zipped publishers结合管道从压缩发布者下载图像
【发布时间】:2021-09-30 08:51:48
【问题描述】:

我在函数中压缩了两个发布者,通过后端 API 下载用户和车辆:

   func fetchUserAndvehicles() {
       Publishers.Zip(UserApiClient().getUser(), VehicleApiClient().getVehicles())
           .eraseToAnyPublisher()
           .receive(on: DispatchQueue.main)
           .sink(receiveCompletion: { [weak self] completion in
               switch completion {
               case .failure(let error):
                   self?.errorHandling.showErrorAlert(error)
               case .finished:
                   break
               }
               }, receiveValue: { [weak self] user, vehicles in
                   // store vehicles in the user object
           })
           .store(in: &subscriptions)
   }

每辆车都有一个imageUrl,可用于下载车辆的图像。这工作正常。但是我想在将车辆存储在用户对象中之前下载图像(如果有的话)。是否可以使用相同的组合管道来执行此操作?我尝试使用flatMap,但导致编译错误。

以下内容来自 Cristik 的出色回答。看起来没问题,但是 Xcode 用 No exact matches in call to instance method 'flatMap' 标记了 flatMap 行:

let vehiclesPublisher = VehicleApiClient().getVehicles()
    .flatMap { vehicles in
        Publishers.Zip(Just(vehicles).setFailureType(to: Error.self), Publishers.MergeMany(vehicles.map { VehicleApiClient().getImage(at: $0.url)}).collect())
    }
    .map {
        return $0.0
    }

车辆有一个可选属性需要解包,但这不是编译错误的原因。

【问题讨论】:

  • 假设您设法拥有一个开始下载所有图像的可编译代码,但是如果其中一些失败了怎么办?是否仍要分配给用户?另外,您的程序上的图片下载情况如何,您有发布商吗?
  • 如果车辆的图片下载失败,我仍然想将车辆分配给用户。我有一个图片下载的发布者。

标签: swift combine


【解决方案1】:

你需要做的是

  1. 将车辆发布者转换为图像下载发布者数组
  2. Create a single publisher from a list of publishers
  3. 等待那个发布者

假设你在某处有一个downloadImage(from url: URL) 函数,并且你的Vehicle 类型有一个imageURL 属性,那么为了完成你所需要的,你必须做的是

let vehiclesPublisher = VehicleApiClient().getVehicles()
    .flatMap { vehicles in
        Publishers.Zip(Just(vehicles).setFailureType(to: Error.self), // setFailureType dance needed
                       Publishers.MergeMany(vehicles.map { downloadImage(from: $0.imageURL) }).collect())
    }.map {
        return $0.0 // unpack the vehicles, so we have back a publisher that outputs [Vehicle]
    }

Publishers.Zip(UserApiClient().getUser(), vehiclesPublisher)
    // rest of the pipeline stays the same

在上面的代码中发生的事情是,我们将车辆数组转换为图像下载器数组,由 collect() 运算符等待。但是我们还需要保留vehicles数组,所以需要一个zip,然后解压zip返回的第一个项目,因为我们不关心图片下载状态,我们只关心所有他们完成。

【讨论】:

  • 看起来棒极了。但我对vehiclesPublisher 有一个编译错误:No exact matches in call to instance method 'flatMap'。我已根据您的建议更新了代码。
  • @IvanCMyrvold 这有点属于一个新问题的范畴。鉴于您提供的有关您拥有的 api 客户端的详细信息很少,因此我很难提供适用于您的代码库的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多