我有一个类似于下面操场示例中的出版商设置.

import Combine

let sub1 = PassthroughSubject<String, Never>().prepend("initial 1")//.share()
let sub2 = PassthroughSubject<String, Never>().prepend("initial 2")

Publishers.CombineLatest(sub1, sub2).sink { content1, content2 in
    print("combined received: \(content1) and \(content2)")
}

sub1.sink { content1 in
    print("first received: \(content1)")
}

sub2.sink { content2 in
    print("second received: \(content2)")
}

如果sub1后面的share()被注释掉,控制台将打印以下内容:

combined received: initial 1 and initial 2
first received: initial 1
second received: initial 2

这似乎在意料之中.但如果存在share(),就会产生意想不到的印记:

combined received: initial 1 and initial 2
second received: initial 2

在我的XCode项目中,我使用prepend()来触发初始执行,但是share()会阻止我的一些链的初始执行. 这是预期中的行为吗?

推荐答案

是的,这是意料之中的.当您使用share时,基本上将发布者更改为引用类型语义.sub1只有一个实例,只要您用sink订阅它,它就会同步发布您预先考虑的第一个元素(prepend是同步的),结果是您在don't之后添加的订阅者将收到您预先考虑的元素.

另一方面,如果不使用share,则完全是值语义.您可以将其视为sink将订阅服务器添加到发布服务器的副本中,这与值类型的复制方式非常相似.然后,每个副本分别发布它们自己的"首字母1".

share的第documentation页中,您可以看到他们通过添加一个延迟解决了这个"share向第一个订阅者同步发布所有元素"的问题:

下面的示例使用序列发布器作为计数器 发布三个随机数,由map(_:)运算符生成.它使用 share()运算符向两个运算符中的每个共享相同的随机数 订阅者.此示例使用 delay(for:tolerance:scheduler:options:)操作员仅用于防止 第一订阅者立即耗尽序列发布者; 一个异步发布者不需要这个.

在您的示例中也可以这样做:

let sub1 = PassthroughSubject<String, Never>()
    .prepend("initial 1")
    .delay(for: 0.1, scheduler: DispatchQueue.main)
    .share()

您将看到"First Receive"行被打印出来.

基本上,发布者现在用它的所有订阅者shares它的元素,如果您想要所有订阅者的初始元素,您需要计算when是否准确地添加了所有订阅者(在上面的例子中,在两个sink之后),并且只有在那个点之后,您才能发布"初始元素"(等待0.1秒之后).否则,某些订阅者不会收到该元素.

Ios相关问答推荐

避免从CoreData加载图像列表时出现SwiftUI挂起

SwiftUI@Observable不跟踪父类属性中的更改以更新视图

如何在将EXPO更新到50.0后修复react 本机错误

如何创建具有SPM依赖项的二进制XCFramework?

IOS-获取本地化系统映像

如何链式设置 AttributeContainer 的 UIKit 属性?

iOS设备网页自动化中,在向字段发送文本后未启用按钮

滚动 swiftUI 列表时,未调用单元格的任务修饰符.怎么修?

弹出视图后使所有背景 UI 模糊

.onChange(of: ) 一次用于多个 @State 属性?

有哪些可靠的机制可以防止 CoreData CloudKit 中的数据重复?

辅助功能判断器无法在 macOS Monterey 版本 12.3 上的 Xcode 版本 13.3 上运行

在 Swift 中执行 while 循环

如何判断是否为 64 位构建了静态库?

从 NSUserDefaults 字典 iOS 中删除所有键

~= Swift 中的运算符

Sierra 中的安全/协同设计: keys 串忽略访问控制设置和 UI 提示权限

在 Objective-C 中将所有文本转换为小写

UISegmentedControl 以编程方式更改段数

如何在 iOS 中获取正在运行的应用程序的名称