合并:将 Closure 转换为 Publisher

Posted

技术标签:

【中文标题】合并:将 Closure 转换为 Publisher【英文标题】:Combine: Convert Closure into Publisher 【发布时间】:2020-05-17 03:23:08 【问题描述】:

如何转换:

func getResults(completion: ([Result]?, Error) -> Void)

进入

var resultsPublisher: AnyPublisher<[Result], Error>

只是我看到的一个方案(这种语法不存在):

var resultsPublisher: AnyPublisher<[Result], Error> 
  let publisher: AnyPublisher = ... // init
  getResults  results, error in
     guard let results = results else 
       publisher.produce(error: error) // this syntax doesn't exist
       return
     

     publisher.produce(results: results)  // this syntax doesn't exist

  

  return publisher

我需要它,因为一些 3d 方 SDK 使用 completion closures,我想为它们编写扩展以返回 Publishers

【问题讨论】:

只需将其包装在 Future 中即可。我只是花了一天时间做这件事!见apeth.com/UnderstandingCombine/publishers/publishersfuture.html 谢谢!你能发布你的答案吗?我会把它标记为正确的,所以它会在未来帮助任何人???? 你没有给我足够的信息让我写一个实际的代码答案,这件事非常初级和明显。但你可以回答你自己的问题! 【参考方案1】:

答案是Future Publisher as matt 解释:

var resultsPublisher: AnyPublisher<[Result], Error> 
    // need deferred when want 
    // to start request only when somebody subscribes 
    // + without Deferred it's impossible to .retry() later
    Deferred  
        Future  promise in
           self.getResults  results, error in
              guard let results = results else 
                 promise(.failure(error))
                 return
              

              promise(.success(results))
           
         
    
    .eraseToAnyPublisher()

【讨论】:

一个想法:在getResults 的第一行放置一个断点,并确保它仅在您期望的时候被调用。有时 Future 需要被包裹在 Deferred 中,我不知道这是否是其中一种情况。 谢谢。似乎 Future 在创建后立即启动,即使没有订阅它,所以对我来说最好使用 Defered + 它允许 .retry() 以防出现错误 很好,很高兴我们发现了这一点。

以上是关于合并:将 Closure 转换为 Publisher的主要内容,如果未能解决你的问题,请参考以下文章

Swift 解析 JSON 时出现问题:无法将“__NSCFDictionary”类型的值转换为“NSArray”错误

如何有效地将 google-closure javascript 转换为现代 ES6?

将 Oracle 合并查询转换为 mysql mySQL 查询

将升序合并排序转换为降序(C)

DFA确定化和最小化

Openpyxl:将单元格与 x y 合并。如何将 id 转换为 Excel 列字母?