Reputation: 127
I'm trying to write a "closure like" combine observers. Let's say I have MyClass
class MyClass {
@Published var value: Int = 0
func doSomethingClosure(completion: (Int?) -> Void) {
value += 1
completion(value)
}
func doSomethingCombine() {
value += 1
}
}
And I can access it using a simple function with closure
let myClass = MyClass()
myClass.doSomethingClosure { (value) in
print(value)
}
Now, I want to do the same using a combine @Published So I will call
var cancelSet: Set<AnyCancellable> = []
myClass.$value
.sink { (value) in
print(value)
}.store(in: &cancelSet)
However, I want it to be triggered only once, so if I call
for _ in 0..<5 {
myClass.doSomethingCombine()
}
I won't get 5 prints but only the first one. One solution I've found for this is cancelling the subscriber inside the sink:
myClass.$value
.sink { (value) in
print(value)
**cancelSet.removeAll()**
}.store(in: &cancelSet)
but I find it kinda "not as intended".
Another solution is using the approach for back pressure, something like:
class MySubscriber: Subscriber {
typealias Input = Int
typealias Failure = Never
func receive(subscription: Subscription) {
subscription.request(.max(1))
}
func receive(completion: Subscribers.Completion<Never>) {
print("Subscription \(completion)")
}
func receive(_ input: Int) -> Subscribers.Demand {
print("Input:\(input)")
return .none
}
}
let mySubscriber = MySubscriber()
myClass.$value.subscribe(mySubscriber)
But I find it cumbersome and overkill for my usage.
Is there any way of implementing "closure style" in a clean way?
Thanks.
Upvotes: 2
Views: 3737
Reputation: 3857
Sounds like a job for https://developer.apple.com/documentation/combine/publishers/prefixwhile/prefix(_:)
let numbers = (0...10)
cancellable = numbers.publisher
.prefix(2)
.sink { print("\($0)", terminator: " ") }
Upvotes: 5