Last active
August 15, 2023 08:20
-
-
Save GeekAndDad/5e381557dc8ba6bc96ebecb17442290e to your computer and use it in GitHub Desktop.
A sketch of a possible approach to mapping a CurrentValueSubject<A,Never> to a CurrentValueSubject<B,Never>. Likely can be simplified and cleaned up, but seems to work...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Test Suite 'Tests' started at 2023-08-15 01:16:43.640 | |
Test Case '-[TestCombineChainingCurrentValueSubjectTests.Tests test]' started. | |
1 | |
12 | |
13 | |
exiting | |
Test Case '-[TestCombineChainingCurrentValueSubjectTests.Tests test]' passed (0.001 seconds). | |
Test Suite 'Tests' passed at 2023-08-15 01:16:43.642. | |
Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.002) seconds | |
Program ended with exit code: 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
import Cocoa | |
import Combine | |
final public class MappedCurrentValueSubject<A, B, Failure, S: CurrentValueSubject<A, Failure>> : Subject | |
where Failure == S.Failure | |
{ | |
public typealias Output = B | |
let upstream: AnyPublisher<S.Output, S.Failure> | |
private let wrapped: CurrentValueSubject<Output, Failure> | |
private let transform: (S.Output) -> Output | |
private var cancellable: AnyCancellable? = nil | |
init(upstream toBeMappedCurrentValueSubject: S, transform: @escaping (S.Output) -> Output) | |
where S.Failure == Failure | |
{ | |
self.upstream = toBeMappedCurrentValueSubject.eraseToAnyPublisher() | |
self.wrapped = CurrentValueSubject<Output, Failure>(transform(toBeMappedCurrentValueSubject.value)) | |
self.transform = transform | |
self.cancellable = upstream.sink { completion in | |
self.send(completion: completion) | |
} receiveValue: { value in | |
self.send(transform(value)) | |
} | |
} | |
public func send(_ value: Output) { | |
wrapped.send(value) | |
} | |
public func send(completion: Subscribers.Completion<Failure>) { | |
wrapped.send(completion: completion) | |
} | |
public func send(subscription: Subscription) { | |
wrapped.send(subscription: subscription) | |
} | |
public func receive<Downstream: Subscriber>(subscriber: Downstream) | |
where Failure == Downstream.Failure, Output == Downstream.Input | |
{ | |
wrapped.subscribe(subscriber) | |
} | |
public func asCurrentValueSubject() -> CurrentValueSubject<Output, Failure> { | |
return wrapped | |
} | |
} | |
extension CurrentValueSubject where Failure == Never { | |
func mappedCurrentValueSubject<T>( | |
transform: @escaping (Output) -> T | |
) -> CurrentValueSubject<T, Failure> | |
{ | |
return MappedCurrentValueSubject<Output, T, Never, CurrentValueSubject<Output, Failure>>( | |
upstream: self, | |
transform: transform | |
).asCurrentValueSubject() | |
} | |
} | |
// Example usage | |
final class Tests: XCTestCase { | |
func test() throws { | |
var cancellables: [AnyCancellable] = [] | |
let num = CurrentValueSubject<Int, Never>(1) | |
let s = num.mappedCurrentValueSubject(transform: { "\($0)" }) | |
s.sink { s in | |
print(s) | |
} | |
.store(in: &cancellables) | |
num.send(12) | |
num.send(13) | |
num.send(completion: .finished) | |
print("exiting") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment