组合中的 Publisher 与 AnyPublisher

Posted

技术标签:

【中文标题】组合中的 Publisher 与 AnyPublisher【英文标题】:Publisher vs AnyPublisher in Combine 【发布时间】:2019-08-28 10:24:22 【问题描述】:

AnyPublisher 在 Combine 中的作用是什么?为什么在许多示例中,包括 inWWDC Combine In practice, 27:40,他们返回 AnyPublisher,使用 .eraseToAnyPublisher,而不仅仅是返回一个 Publisher?

Apple Documents 说

使用 AnyPublisher 包装一个发布者,其类型包含您不想向订阅者或其他发布者公开的详细信息。

但是谁能举个例子说明它在哪里有用?

【问题讨论】:

你应该阅读类型擦除。 This 文章很好地解释了类型擦除背后的原因以及为什么要使用它。请记住,Swift 5.1 的不透明返回类型解决了无法将 PAT 用作具体类型的问题,这是以前使用类型擦除的主要原因之一,但其他用例仍然适用。 【参考方案1】:

Publisher 是一个具有关联类型的协议,而AnyPublisher 是一个结构

尝试转换为 Publisher 会出现错误

let x = Just(1) as Publisher

Protocol 'Publisher' 只能用作通用约束,因为它具有 Self 或关联的类型要求

尽管JustPublisher

Publisher 类型不能像AnyPublisher 一样使用来实现类型擦除。

您可以使用Publisher 的地方是当您定义一个将泛型作为定义的一部分的函数时。

使用AnyPublisher 的最常见原因:

从函数返回一个发布者的实例。

使用Publisher 的最常见原因:

创建协议扩展以创建自定义组合运算符。例如:

extension Publisher 
  public func compactMapEach<T, U>(_ transform: @escaping (T) -> U?)
    -> Publishers.Map<Self, [U]>
    where Output == [T]
  
    return map  $0.compactMap(transform) 
  

【讨论】:

只使用some Publisher 怎么样?那行得通 @smat88dd 如果你有更好的答案,请补充! @smat88dd 我认为some Publisher 在编译器转换为具体类型时会导致一些错误。所以这不是一个选择。【参考方案2】:

Publisher 是一种协议,AnyPublisher 是 Publisher 的具体实现。

AnyPublisher 是符合 Publisher 协议的类型擦除结构。类型擦除允许隐藏可能不希望向订阅者或下游发布者公开的发布者的详细信息。

注意: AnyPublisher 没有 send(_:) 运算符,因此无法向该发布者添加新值。

【讨论】:

以上是关于组合中的 Publisher 与 AnyPublisher的主要内容,如果未能解决你的问题,请参考以下文章

GA 到 BigQuery 导出架构中的“hits.publisher.adsRevenue”字段是啥意思?

Publisher 中的 Publisher 不会触发 SwiftUi 重新渲染

编写第一个ROS程序-发布器(Publisher)

dustindiaz&ŧ039;的Publisher类实现了javascript中的Publisher-subscriber模式

可以直接使用 Publisher 作为 SwiftUI 中的 @ObjectBinding 属性吗?

将 MQTT 消息与 Publisher 的 clienID 连接