【问题标题】:combineLatest on CurrentValueSubject doesn't emit when combining with @Published property与 @Published 属性结合时,CurrentValueSubject 上的 combineLatest 不会发出
【发布时间】:2020-08-18 20:14:59
【问题描述】:

我正在使用与 Swift5 结合使用;我有一个 CurrentValueSubject,我正在与一个 @Published 字典变量组合。

问题是当当前值被更新时,map 永远不会被调用!这特别是 @Published 变量的问题,因为它适用于未使用 @Published 的其他流。

@Published var userModels: [String: UserModel] = [:]
var chatModels: CurrentValueSubject<[ChatModelFirebase], Never> = CurrentValueSubject([])

chatModels
    .combineLatest(userModels.publisher)
    .map({ (chatModels, userModels) -> [ChatViewModel] in
        print("Hello") // Never gets called! ????
        return []
        })
.assign(to: \.chatViewModels, on: self)
.store(in: &cancellableSet)


// Update chat model's value, and notice that map never gets called!
chatModels.values = []

没有错误,代码编译运行,但我从来没有得到流更新的结果。 如果我将userModels 更新为CurrentValueSubject,问题将得到解决,但问题是为什么combineLatest(..)@Published 中断?

【问题讨论】:

  • 它永远不会被调用,因为userModels 是空的,所以userModels.publisher 发送0 个值,而combineLatest 从不发送一个元组(它至少在等待第一个值)
  • @NewDev combineLatest 文档指出,当任何一个发布者发出 Subscribes to an additional publisher and publishes a tuple upon receiving output from either publisher. 时都会调用它,请参阅 developer.apple.com/documentation/combine/currentvaluesubject。因此,即使 userModels 为空,对 chatModels 的任何更新都应该得到反映。
  • 是的,但它至少等待每个值的第一个值(否则,它不能形成一个元组)。之后,它在其中一个中发布一个新值,并结合另一个中的最新值
  • 另外,请记住,您实际上并没有使用 Published 发布者 - 您正在使用字典的 Sequence 发布者。如果userModels 发生变化,这不会将新值发送到您的管道中。如果您想使用 Published 发布者 - 您应该使用:$userModels

标签: ios swift swift5 combine


【解决方案1】:

我认为您混淆了两个发布者:Published&lt;Value&gt;.Publisher 发布者通过$userModels@Published 属性创建,Publishers.Sequence 发布者通过userModels.publisher 获得。


Published 会发布每次更改的值。因此,$userModels 将立即发布 [:] 值,然后在每次更改时再次发布:

class Foo {
  @Published var dict: [String: Int] = [:]
}
let foo = Foo()

foo.$dict
   .sink { print($0) }

foo.dict = ["one": 1, "two": 2]

输出是:

[:]
["one": 1, "two": 2]

Sequence 发布者发布序列中的每个值,对于字典来说,序列是一系列 (key, value) 的元组。对于空序列,它会发布 no values

var dict: [String: Int] = [:]

dict.publisher
  .sink { print($0) } // will not print anything

在您的情况下,您将 .combineLatest 与来自空字典的 Sequence 发布者一起使用,该字典不发布任何值,因此 CombineLatest 不发布任何值。

您可能正在寻找的是订阅Published 发布者userModels 属性:

chatModels.combineLatest($userModels)
   .sink { print($0) }   

然后初始输出将立即为:

([:], [])

【讨论】:

    猜你喜欢
    • 2020-02-28
    • 2021-05-13
    • 2021-04-01
    • 2020-08-21
    • 2018-09-29
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    • 2020-11-21
    相关资源
    最近更新 更多