【问题标题】:Swift Combine: collect after sequence publisher not calledSwift Combine:在未调用序列发布者之后收集
【发布时间】:2021-02-24 16:26:14
【问题描述】:

我有一个发送/接收数据数组的主题,例如PassthroughSubject<[Int], Never>()。当收到一个值时,我想将数组拆分为单个值来操作它们,然后再次收集它们。

我知道问题在于flatMap 永远不会发送完成事件。但是我该如何解决这个问题?或者有没有更好的方法来使用 combine 操作数组中的每个值?

编辑: 我不想完成要收集的主题。我想收集音序器的输出。

例子:

import Combine

var storage = Set<AnyCancellable>()
let subject = PassthroughSubject<[Int], Never>()

subject
    .flatMap { $0.publisher }
    .map { $0 * 10 }
    .collect()
    .sink {
        print($0) // Never called
    }
    .store(in: &storage)

subject.send([1, 2, 3, 4, 5])

【问题讨论】:

    标签: swift combine


    【解决方案1】:

    我找到了实现预期结果的解决方案。我不得不在flatMap 中移动mapcollect

    import Combine
    
    var storage = Set<AnyCancellable>()
    let subject = PassthroughSubject<[Int], Never>()
    
    subject
        .flatMap { $0.publisher
            .map { $0 * 10 }
            .collect()
        }
        .sink {
            print($0)
        }
        .store(in: &storage)
    
    subject.send([1, 2, 3, 4, 5])
    subject.send([1, 2, 3, 4, 5].reversed())
    

    这将打印[10, 20, 30, 40, 50][50, 40, 30, 20, 10]

    【讨论】:

    【解决方案2】:

    您不需要flatMap()collect() 调用,您可以简单地通过接收到的数组map()

    subject
        .map { $0.map { $0 * 10 } }
        .sink {
            print($0) // Now it's called :)
        }
        .store(in: &storage)
    
    subject.send([1, 2, 3, 4, 5])
    

    【讨论】:

    • 谢谢!这个答案帮助我找到了解决方案:)
    【解决方案3】:

    collect 等待发布者完成。 PassthroughSubject 不会自动完成。你需要拨打send(completion:就可以了。

    subject.send([1, 2, 3, 4, 5])
    subject.send(completion: .finished) // now `sink` will be triggered
    

    【讨论】:

    • 但是不想完成题目怎么办?
    • @Noroxs 不要使用collectcollect 的全部意义在于等待发布者完成然后才发出值,因为它收集 all 值并且它只能知道 all 值是发布者完成后发出。您也可以使用collect(5) 在每次发布 5 个值时发出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 2019-11-08
    • 2019-11-16
    • 1970-01-01
    相关资源
    最近更新 更多