我如何才能等到所有 Combine 发布者在 Swift 完成他们的工作?
How can I wait until all Combine publishers finished their jobs in Swift?
我希望在所有 Combine 发布商像 DispatchGroup
和 .notify
那样完成工作时收到通知。
例如,在下面的代码中,我想在发布者(pub1
、pub2
)执行他们的工作时显示 ProgressView
。
import Combine
import Foundation
import SwiftUI
struct SwiftUIView: View {
@State var isFinished = false
let pub1 = ["one", "two", "three", "four"].publisher
let pub2 = ["five", "six", "seven", "eight"].publisher
var subscriptions = Set<AnyCancellable>()
var body: some View {
if isFinished {
Text("Hello, World!")
} else {
ProgressView()
}
}
init() {
pub1
.sink { print([=11=]) }
.store(in: &subscriptions)
pub2
.sink { print([=11=]) }
.store(in: &subscriptions)
// Where should I write this code?
// isFinished = true
}
}
我的问题是我如何才能等到发布商完成并在正确的时间显示“Hello world”?
有什么我应该知道的吗?如果是这样,请告诉我。谢谢!
一种可能的方法是视图模型。在此 class merge
发布者并使用 receiveCompletion:
参数
class ViewModel : ObservableObject {
@Published var isFinished = false
let pub1 = ["one", "two", "three", "four"].publisher
let pub2 = ["five", "six", "seven", "eight"].publisher
private var subscriptions = Set<AnyCancellable>()
init() {
pub1
.sink { print([=10=]) }
.store(in: &subscriptions)
pub2
.sink { print([=10=]) }
.store(in: &subscriptions)
pub1.merge(with: pub2)
.sink(receiveCompletion: { _ in
self.isFinished = true
}, receiveValue: { _ in })
.store(in: &subscriptions)
}
}
struct SwiftUIView: View {
@StateObject private var model = ViewModel()
var body: some View {
if model.isFinished {
Text("Hello, World!")
} else {
ProgressView()
}
}
}
您可以使用 Zip 运算符。 Zip 操作员仅在收到来自所有发布者的事件后才发布。另一方面,每当其中一个发布者发布新值时,Merge 都会发布。
class ViewModel : ObservableObject {
@Published var isFinished = false
let pub1 = ["one", "two", "three", "four"].publisher
let pub2 = ["five", "six", "seven", "eight"].publisher
private var cancelable = Set<AnyCancellable>()
init() {
pub1.zip(pub2)
.sink(receiveCompletion: { _ in
self.isFinished = true
}, receiveValue: {
print("\([=10=]),\()")
})
.store(in: &cancelable)
}
}
struct SwiftUIView: View {
@StateObject private var model = ViewModel()
var body: some View {
if model.isFinished {
Text("Hello, World!")
} else {
ProgressView()
}
}
}
我希望在所有 Combine 发布商像 DispatchGroup
和 .notify
那样完成工作时收到通知。
例如,在下面的代码中,我想在发布者(pub1
、pub2
)执行他们的工作时显示 ProgressView
。
import Combine
import Foundation
import SwiftUI
struct SwiftUIView: View {
@State var isFinished = false
let pub1 = ["one", "two", "three", "four"].publisher
let pub2 = ["five", "six", "seven", "eight"].publisher
var subscriptions = Set<AnyCancellable>()
var body: some View {
if isFinished {
Text("Hello, World!")
} else {
ProgressView()
}
}
init() {
pub1
.sink { print([=11=]) }
.store(in: &subscriptions)
pub2
.sink { print([=11=]) }
.store(in: &subscriptions)
// Where should I write this code?
// isFinished = true
}
}
我的问题是我如何才能等到发布商完成并在正确的时间显示“Hello world”?
有什么我应该知道的吗?如果是这样,请告诉我。谢谢!
一种可能的方法是视图模型。在此 class merge
发布者并使用 receiveCompletion:
参数
class ViewModel : ObservableObject {
@Published var isFinished = false
let pub1 = ["one", "two", "three", "four"].publisher
let pub2 = ["five", "six", "seven", "eight"].publisher
private var subscriptions = Set<AnyCancellable>()
init() {
pub1
.sink { print([=10=]) }
.store(in: &subscriptions)
pub2
.sink { print([=10=]) }
.store(in: &subscriptions)
pub1.merge(with: pub2)
.sink(receiveCompletion: { _ in
self.isFinished = true
}, receiveValue: { _ in })
.store(in: &subscriptions)
}
}
struct SwiftUIView: View {
@StateObject private var model = ViewModel()
var body: some View {
if model.isFinished {
Text("Hello, World!")
} else {
ProgressView()
}
}
}
您可以使用 Zip 运算符。 Zip 操作员仅在收到来自所有发布者的事件后才发布。另一方面,每当其中一个发布者发布新值时,Merge 都会发布。
class ViewModel : ObservableObject {
@Published var isFinished = false
let pub1 = ["one", "two", "three", "four"].publisher
let pub2 = ["five", "six", "seven", "eight"].publisher
private var cancelable = Set<AnyCancellable>()
init() {
pub1.zip(pub2)
.sink(receiveCompletion: { _ in
self.isFinished = true
}, receiveValue: {
print("\([=10=]),\()")
})
.store(in: &cancelable)
}
}
struct SwiftUIView: View {
@StateObject private var model = ViewModel()
var body: some View {
if model.isFinished {
Text("Hello, World!")
} else {
ProgressView()
}
}
}