swift - 订阅发布者时无法获取最新值
问题描述
我有一个在用户登录和注销时注册/注销的侦听器。我有类似于以下代码的东西,
import Foundation
import Combine
class X : ObservableObject {
@Published var data: String? = nil
func setData() {
data = "DATA"
}
}
let x = X()
var store = Set<AnyCancellable>()
x.$data.sink { v1 in // I need to add .receive(on:) here
print(v1)
if v1 != nil {
x.$data.sink { v2 in
print(v2) // Why is this nil
}.store(in: &store)
}
}.store(in: &store)
x.setData()
我以为v2
会这样"DATA"
,但事实并非如此。我需要.receive(on: DispatchQueue.main)
在外部订阅中做一个让他们都收到“之后”状态。
我的工作理论是,在调用所有处理程序之后不会写入值,因为我不知道如何验证它,更不用说它是否正确。
为什么receive(on:)
这里有必要?
我知道我可以使用
flatMap
,但我没有使用它,因为我的状态传递得太晚了,我需要在退出代码运行之前取消订阅内部映射的发布者以避免权限问题。
解决方案
这里发生的是一种非常微妙的行为。
该表达式的x.$data
计算结果为 a Published.Publisher
。当您订阅 aPublished.Publisher
时,它会立即发布其当前值,然后每次Published
属性接收到新值时,发布者都会在新值存储到属性中之前发布新值。
此行为记录在Published
参考资料中:
当属性更改时,发布发生在属性的
willSet
块中,这意味着订阅者会在新值实际设置在属性上之前收到新值。
这意味着当您调用时x.setData()
,外部订阅会在 中接收新值 ( "DATA"
) v1
,但x.data
此时仍会计算为nil
。并且当您创建内部订阅时x.$data
,它会立即发布其当前存储的值,该值仍然是nil
.
推荐阅读
- amazon-web-services - 如何将授权/api 密钥附加到 sam cli 生成的 api?
- javascript - 当任何用户登录而不使用信号器单击按钮时如何获取实时用户名?
- javascript - Angular HighCharts ParlimentChart 不工作
- angular - AWS、S3 Bucket 上的 Angular、ec2 实例上的 Spring boot(使用 Elastic Beanstalk 创建)和负载均衡器
- excel - VBA Shapes(Application.Caller).TopLeftCell.Row 返回不正确的行
- javascript - 在 Java Script 中将图像添加到按钮中
- python - 通过套接字将浮点数从 Python 发送到 C#
- javascript - 异步调用 faceapi.detectAllFaces()
- dns - URL 掩蔽或隐藏
- python - PyQt5 无法将滑块链接到我的 mp3 播放器中正在播放的音频