我找到了使用MergeManyor组合发布商的方法CombineLatest,但在我的特定情况下似乎没有找到解决方案。
例子:
class Test {
@Published var firstNameValid: Bool = false
@Published var lastNameValid: Bool = false
@Published var emailValid: Bool = false
@Published var allValid: Bool = false
}
Run Code Online (Sandbox Code Playgroud)
我想allValid成为false当任何以前的出版商被设置为false,并且true如果他们全部都是true。我也不想对我正在观察的发布商列表进行硬编码,因为我想要一个灵活的解决方案,所以我希望能够将Bool发布商数组传递给我用来执行此操作的任何代码。
我试过这个
let fieldPublishers = [$firstNameValid, $lastNameValid, $emailValid]
Publishers
.MergeMany(fieldPublishers)
.sink { [weak self] values in
self?.allValid = values.allSatisfy { $0 }
}
.store(in: &subscribers)
Run Code Online (Sandbox Code Playgroud)
但这当然行不通,因为我得到的是发布者数组,而不是值数组。sink我尝试了一些其他方法(忘记了哪些方法),但它们似乎只有在我在执行期间为所有 3 个发布者分配了一个值时才会调用。
在只使用 2 个发布者的情况下,我设法使用CombineLatest.
所以问题是:sink当数组中只有一个发布者在实例化后更改值时Test,我是否可以触发,然后迭代我正在观察的所有发布者的值?
结合最新确实是正确的。您有三个发布商,因此您将使用CombineLatest3。在这个例子中,我使用 CurrentValueSubjectpublishers 而不是@Published,但原理是一样的:
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 {
let b1 = CurrentValueSubject<Bool,Never>(false)
let b2 = CurrentValueSubject<Bool,Never>(false)
let b3 = CurrentValueSubject<Bool,Never>(false)
var storage = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
Publishers.CombineLatest3(b1,b2,b3)
.map { [$0.0, $0.1, $0.2] }
.map { $0.allSatisfy {$0}}
.sink { print($0)}
.store(in: &self.storage)
// false
delay(1) {
self.b1.send(true) // false
delay(1) {
self.b2.send(true) // false
delay(1) {
self.b3.send(true) // true
delay(1) {
self.b1.send(false) // false
delay(1) {
self.b1.send(true) // true
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,现在你可能会抱怨,这对于硬编码的三个发布商来说没问题,但我想要任意数量的发布商。美好的!从一组发布者开始,使用 JointLatest 一次累积一个发布者,以形成一个生成 Bool 数组的发布者:
let list = [b1, b2, b3] // any number of them can go here!
let pub = list.dropFirst().reduce(into: AnyPublisher(list[0].map{[$0]})) {
res, b in
res = res.combineLatest(b) {
i1, i2 -> [Bool] in
return i1 + [i2]
}.eraseToAnyPublisher()
}
pub
.map { $0.allSatisfy {$0}}
.sink { print($0)}
.store(in: &self.storage)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8720 次 |
| 最近记录: |