【问题标题】:How to force an initial value when creating a pipe with CurrentValueSubject in Combine in Swift 5?在 Swift 5 中的 Combine 中使用 CurrentValueSubject 创建管道时如何强制使用初始值?
【发布时间】:2020-08-19 18:25:42
【问题描述】:

我正在尝试获取 EventDetailsModel 的初始值并订阅所有未来的更新。

当我调用eventDetails(..) 时,所有发布者都已经有了一些当前值(即chatModelsuserModels 有10 多个项目);问题是因为没有新的更新,所以生成的管道永远不会返回 EventDetailModels,因为 .map(...) 永远不会被调用。

如何让组合管道在构建时至少通过现有值一次,以便我的接收器具有一些初始值?

var chatModels: Publishers.Share<CurrentValueSubject<[ChatModel], Never>> = CurrentValueSubject([]).share()
var userModels: CurrentValueSubject<[String: UserModel], Never> = CurrentValueSubject([:])

func eventDetails(forChatId chatId: String) -> AnyPublisher<EventDetailsModel?, Never> {
    return chatModels
        .combineLatest(userModels)
        .map({ (chatList, userModels) -> EventDetailsModel? in
            // Never gets called, even if chatModels and userModels has some existing data ????
            if let chatModel = (chatList.first { $0.id == chatId}) {
                return EventDetailsModel(chatModel, userModels)
            }
            return nil
        })
        .eraseToAnyPublisher()
}

【问题讨论】:

  • 第二个问题大致相同。也许,与其问如何使这个特定的事情发挥作用,不如扩大问题范围以描述您实际想要实现的目标。
  • @NewDev 是的,这可能是一个 x-y 问题。我的猜测是,OP 真正想要的只是使用chatModels 作为发布者,然后是添加userModelsflatMap。但如果没有关于目标的实际信息,就不可能说出来。
  • @matt 更新了更高级别的目标,我几乎想获取一个初始值并听取后续更新。问题是我得到了后续更新,但没有得到初始值。
  • 好的,刚刚注意到chatModelsPublishers.Share,不知道这是否改变了语义。
  • 主题不需要.share。无论如何,主题都是引用类型

标签: ios swift swift5 combine


【解决方案1】:

使用combineLatest,您不会收到任何事件,直到两个发布者都有最新消息。这就是combineLatest 的意思。这里的问题不是chatModels,它确实有一个最新的。问题是userModels。在它首次发布之前,您不会在此管道中收到任何事件。

编辑好的,现在您已经更新了代码以显示两个您的发布者都是 CurrentValueSubjects。好吧,在这种情况下,您确实会收到一个初始事件,正如这个玩具示例所证明的那样:

var storage = Set<AnyCancellable>()
let sub1 = CurrentValueSubject<Int,Never>(1)
let sub2 = CurrentValueSubject<String,Never>("howdy")
override func viewDidLoad() {
    super.viewDidLoad()
    sub1.combineLatest(sub2)
}

因此,如果您没有发生这种情况,那么问题就出在其他地方。例如,也许您忘记了store 您的管道,因此您根本无法获得任何事件。 (但谁知道呢?你把相关代码隐藏了。)

【讨论】:

  • 更新了我的问题以表明 userModelschatModels 都使用一些数据进行了初始化。我的直觉是,除非有未来的事件发出,.map() 不会被当前设置调用,无论初始数据如何。
  • 好吧,我向你保证,如果你真的有两个 CurrentValueSubjects 并且你用它们做一个 CombineLatest,你确实得到一个事件。所以问题一定出在其他地方。但谁知道呢?你一直对我们隐藏你的代码。
  • 我没有隐藏代码。我只想简化,因为如果我添加我的代码库,它会变得更难阅读。我相信你已经明白了。
  • 不,我不知道。例如,您引用sink。但是没有没有水槽。但是您仍然希望我们能够帮助您吗?此外,我已经向展示了足够的代码来展示做什么工作。但是您没有显示足够的代码来重现 不起作用 工作。我相信你明白minimal reproducible example 是什么。
  • 我想在那里添加水槽,但认为它的作用是不言而喻的 ?‍♂️。发现它来自于将chatModel 包裹在Publishers.Share 中,不知道为什么会这样做。如上所述,将两者都切换为 CurrentValueSubject 有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-23
  • 1970-01-01
  • 1970-01-01
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 2020-01-06
相关资源
最近更新 更多