swift 快速从对象数组Map到异步函数数组,并等待它们全部

rslzwgfq  于 2022-12-02  发布在  Swift
关注(0)|答案(1)|浏览(125)

我刚刚更新到Xcode 13.2.1,现在可以访问异步等待,我正试图找到我可以从合并“转换”到异步等待的地方。
我想实现以下目标...
如果是像...

struct Person {
  let name: String

  func fetchAvatar(completion: @escaping (UIImage?) -> Void) {
    // fetch the image from the web and pass it into the completion.
  }
}

我现在有一个这样的功能......

func fetchAllTheAvatars(people: [Person], completion: ([UIImage]) -> Void) {
  Publisher.MergeMany(
    people.map { person in
      Future<UIImage?, Never> { promise in
        person.fetchAvatar { promise(.success($0)) }
      }
    }
  )
  .compactMap { $0 }
  .collect()
  .sink { completion($0) }
  .store(in: &cancellables )
}

现在......在我看来,这可能是一个很好的候选人,转移到使用异步等待和AsyncSequence也许......?!?它不一定是理想的,虽然,我只是想得到一个如何使用它们的感觉。我习惯了async await在JS和TS和这似乎只是有点不同。:D
我在Person中添加了一个 Package 函数...

func fetchAvatar() async -> UIImage? {
  await withCheckedContinuation { continuation in
    fetchAvatar { image in
      continuation.resume(returning: image)
    }
  }
}

但是现在我陷入了如何更新我的fetchAllTheAvatars函数的困境。

func fetchAllTheAvatars(people: [Person]) async -> [UIImage] {
  people.map { ...???... }
}

我在网上看到的所有地方似乎都使用for await line in url.lines { ... },但我还没有一个AsyncSequence。我需要以某种方式将我的Person的非异步数组“转换”为() -> Image?AsyncSequence
这可能吗?我是不是走错路了?
谢谢

djmepvbi

djmepvbi1#

标准模式是TaskGroup。为单个图像添加任务,然后在for循环中添加awaitmap,或者在本例中添加reduce

func fetchAllTheAvatars(people: [Person]) async -> [Person.ID: UIImage] {
    await withTaskGroup(of: (Person.ID, UIImage?).self) { group in
        for person in people {
            group.addTask { await (person.id, person.fetchAvatar()) }
        }
        
        return await group.reduce(into: [:]) { dictionary, result in 
            if let image = result.1 {
                dictionary[result.0] = image
            }
        }
    }
}

注意,由于顺序不受保证,而且某些Person可能不返回图像,因此我的实现返回一个有效的、与顺序无关的结构(即字典)。
不用说,上面的代码假定您使Person符合Identifiable

struct Person: Identifiable {
    let id = UUID()
    let name: String
    
    func fetchAvatar() async -> UIImage? { … }
}

相关问题