合并分配发布者到 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
,证明我们正在删除重复项,并且联网 是实际发生在每一个场合,你可以用其他方式向自己证明。
我有以下 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
,证明我们正在删除重复项,并且联网 是实际发生在每一个场合,你可以用其他方式向自己证明。