合并分配发布者到 PassthroughSubject

Combine assign publisher to PassthroughSubject

我有以下 RxSwift 视图模型代码:

private(set) var num = BehaviorRelay<Int>(value: 1)
private let indexTrigger = PublishRelay<Int>()
private let disposeBag = DisposeBag()

private func setupBindings() {
   //...
   self.num.distinctUntilChanged().bind(to: self.indexTrigger).disposed(by: self.disposeBag)
}

func numSelected(num: Int) {
   self.num.accept(num)
}

这段代码运行良好,可以满足我的要求。我正在尝试做同样的事情,但是 swift 将框架与以下代码结合使用:

@Published private(set) var num: Int = 1
private let indexTrigger = PassthroughSubject<Int, Never>()
private var subscriptions = Set<AnyCancellable>()

private func setupBindings() {
   //...
   self.$num.removeDuplicates().sink(receiveValue: { [weak self] num in
      self.indexTrigger.send(num)
   }).store(in: &self.subscriptions)
}

func numSelected(num: Int) {
   self.num = num
}

因此 RxSwift 绑定看起来更加简洁明了,而且不需要 weak。我试图在 combine 中检查 assign(on:) 方法,但似乎不是那个方法。有没有办法做同样的事情?

您似乎在尝试“链接”发布商。链接发布者的方法是不要有两个独立的发布者,第二个发布者由 .sink.send 戳;它是在管道中使用.flatMap

在您的评论中,您说您真正想在第二个发布者中做的是“触发请求”。这听起来像网络。因此,在您的 .flatMap 中,您将提供一个进行网络连接的发布者。

这里有一个 玩具 例子,只是为了给你展示形式:

import UIKit
import Combine

func delay(_ delay:Double, closure:@escaping ()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}

class ViewController: UIViewController {

    @Published var num: Int = 1
    var storage = Set<AnyCancellable>()
    
    func setupPipeline() {
        $num.removeDuplicates()
            .flatMap { self.makeNetworkingFuture([=10=]) }
            .sink { print([=10=]) }
            .store(in: &self.storage)
    }
    
    func makeNetworkingFuture(_ i: Int) -> AnyPublisher<Int,Never> {
        URLSession.shared.dataTaskPublisher(for: URL(string:"https://www.example.com")!)
            .map{_ in i}
            .replaceError(with: -1000)
            .eraseToAnyPublisher()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setupPipeline()
        delay(1) { self.num = 1 }
        delay(2) { self.num = 1 }
        delay(3) { self.num = 2 }
        delay(4) { self.num = 2 }
        delay(5) { self.num = 3 }
    }
}

这是一个非常愚蠢的例子,从某种意义上说,虽然我们做了一些网络,但我们没有显示该网络的 结果。我只是输出一个 Int(与从 num 流出管道的 Int 相同)。但是当你 运行 这个例子时,你会在输出中看到 1,然后是 2,然后是 3,证明我们正在删除重复项,并且联网 实际发生在每一个场合,你可以用其他方式向自己证明。