Comments (3)
I am not sure if this can be solved. Some Combine operators stop working when you erase the Publisher, and removeDuplicates is one of them. I open FB7742987 for a problem of using removeDuplicates in an "onReceive" SwiftUI modifier, which causes cancellation after every event, and it's somehow similar to the behaviour you described.
I'm gonna review the wrapper code to check if there's anything wrong there, but otherwise I can open another Radar for that.
from swiftrex.
Playground code if you want to check:
import Combine
import Dispatch
import PlaygroundSupport
import SwiftUI
let subject1 = PassthroughSubject<Int, Never>()
struct ContentView: View {
@State var accumulated: [String] = []
@State var last: Int = 0
var body: some View {
VStack {
Button("Tap") {
self.last += 1
subject1.send(self.last)
}
Text(accumulated.joined(separator: ", "))
}.onReceive(
subject1
//.removeDuplicates()
.throttle(
for: .milliseconds(500),
scheduler: DispatchQueue.main,
latest: true
)
.handleEvents(receiveCancel: {
print("cancel")
})
//.removeDuplicates()
//.eraseToAnyPublisher()
) { value in
self.accumulated += ["\(value)"]
}
}
}
PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())
from swiftrex.
Closing this as it's a problem in Combine, that still happens in recent versions of Swift (5.8).
A workaround is to write your own Remove Duplicates. I just wrote an example one that is by no means productions ready - it's not thread-safe, it's not following the backpressure standard, it's probably full of bugs and memory leaks -, but it's proving my point (that means, it will work as expected for the scenario above):
import Foundation
extension Publisher {
public func removeDuplicatesEx(by predicate: @escaping (Output, Output) -> Bool) -> Publishers.RemoveDuplicatesEx<Self> {
return .init(upstream: self, predicate: predicate)
}
}
extension Publishers {
public struct RemoveDuplicatesEx<Upstream: Publisher>: Publisher {
public typealias Output = Upstream.Output
public typealias Failure = Upstream.Failure
public let upstream: Upstream
public let predicate: (Upstream.Output, Upstream.Output) -> Bool
public init(upstream: Upstream, predicate: @escaping (Publishers.RemoveDuplicatesEx<Upstream>.Output, Publishers.RemoveDuplicatesEx<Upstream>.Output) -> Bool) {
self.upstream = upstream
self.predicate = predicate
}
public func receive<S: Subscriber>(subscriber: S) where Upstream.Output == S.Input, S.Failure == Publishers.RemoveDuplicatesEx<Upstream>.Failure {
let s = Inner(predicate: predicate, upstream: upstream, downstream: subscriber)
subscriber.receive(subscription: s)
}
}
}
extension Publishers.RemoveDuplicatesEx {
private final class Inner<Subscriber: Combine.Subscriber>: Combine.Subscription
where
Subscriber.Input == Output,
Subscriber.Failure == Failure {
typealias Input = Upstream.Output
typealias Failure = Upstream.Failure
typealias Predicate = (Upstream.Output, Upstream.Output) -> Bool
let predicate: Predicate
let downstream: Subscriber
var upstreamSubscription: AnyCancellable?
var previous: Output?
init(predicate: @escaping (Output, Output) -> Bool, upstream: Upstream, downstream: Subscriber) {
self.predicate = predicate
self.downstream = downstream
upstreamSubscription = upstream.sink(receiveCompletion: { completion in
self.receive(completion: completion)
}, receiveValue: { output in
self.receive(output)
})
}
func cancel() {
}
func request(_ demand: Subscribers.Demand) {
}
func receive(_ input: Input) -> Subscribers.Demand {
guard let previous = self.previous else {
self.previous = input
_ = self.downstream.receive(input)
return .unlimited
}
if self.predicate(previous, input) {
self.previous = input
_ = self.downstream.receive(input)
}
return .unlimited
}
func receive(completion: Subscribers.Completion<Failure>) {
self.downstream.receive(completion: completion)
}
}
}
from swiftrex.
Related Issues (20)
- middleware lift with WritableKeyPath doesn't work on AnyMiddleware HOT 2
- Fix animations from Middleware
- Dead-Letter Queue HOT 1
- Memory leak in LiftMiddleware
- When will develop be the official release? HOT 2
- Lift EffectMiddleware using KeyPath not receiving context
- How to modify AppLifecycleMiddleware to adopt the new MiddlewareProtocol? HOT 2
- Redundant conformance of 'ASAPScheduler' to protocol 'Scheduler'
- Using await/async in middleware HOT 4
- IO monad and stack limit HOT 6
- I think it's time to enable Enabling Concurrency warnings in Xcode HOT 2
- Dynamic store HOT 5
- Migrate away from Travis CI HOT 4
- Design question : Model to State migration HOT 2
- Dispatch actions and run reducers on background thread? HOT 4
- Trying to use Effect.promise with Firebase's DynamicLinkComponents.shortenURL HOT 5
- Question about assertionFailure() HOT 5
- How organize communication between different states HOT 2
- Improve Tests
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from swiftrex.