Last active
March 11, 2020 23:58
-
-
Save drumnkyle/5a8a3fd4f92ec19f9d613fd02d40b795 to your computer and use it in GitHub Desktop.
Erasing Combine Subjects Property Wrapper
This file contains 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
#if canImport(Combine) | |
import Combine | |
@propertyWrapper | |
/// Provides a property wrapper whose projected value is a `PassthroughSubject`, but | |
/// the wrapped value is just an `AnyPublisher`. This allows you to make a property with | |
/// availability declared for only iOS 13+ and hide the actual publisher. | |
public struct ErasedPassthroughSubject<Output, Failure: Error> { | |
private var value: Any? | |
@available(iOS 13.0, tvOS 13.0, OSX 10.15, *) | |
public var wrappedValue: AnyPublisher<Output, Failure> { | |
return passthroughSubject().eraseToAnyPublisher() | |
} | |
@available(iOS 13.0, tvOS 13.0, OSX 10.15, *) | |
public var projectedValue: PassthroughSubject<Output, Failure> { | |
return passthroughSubject() | |
} | |
/// Creates the underlying `PassthroughSubject` automatically. | |
public init() { | |
if #available(iOS 13.0, tvOS 13.0, OSX 10.15, *) { | |
self.value = PassthroughSubject<Output, Failure>() | |
} else { | |
self.value = nil | |
} | |
} | |
@available(iOS 13.0, tvOS 13.0, OSX 10.15, *) | |
private func passthroughSubject() -> PassthroughSubject<Output, Failure> { | |
return (value as? PassthroughSubject) ?? PassthroughSubject() | |
} | |
} | |
@propertyWrapper | |
/// Provides a property wrapper whose projected value is a `CurrentValueSubject`, but | |
/// the wrapped value is just an `AnyPublisher`. This allows you to make a property with | |
/// availability declared for only iOS 13+ and hide the actual publisher. | |
public struct ErasedCurrentValueSubject<Output, Failure: Error> { | |
private var value: Any? | |
private var firstValue: Output | |
@available(iOS 13.0, tvOS 13.0, OSX 10.15, *) | |
public var wrappedValue: AnyPublisher<Output, Failure> { | |
return currentValueSubject().eraseToAnyPublisher() | |
} | |
@available(iOS 13.0, tvOS 13.0, OSX 10.15, *) | |
public var projectedValue: CurrentValueSubject<Output, Failure> { | |
return currentValueSubject() | |
} | |
/// Initialize with a current value. | |
/// - Parameter currentValue: The current value to initialize the `CurrentValueSubject` | |
/// with. | |
public init(currentValue: Output) { | |
firstValue = currentValue | |
if #available(iOS 13.0, tvOS 13.0, OSX 10.15, *) { | |
self.value = CurrentValueSubject<Output, Failure>(currentValue) | |
} else { | |
self.value = nil | |
} | |
} | |
@available(iOS 13.0, tvOS 13.0, OSX 10.15, *) | |
private func currentValueSubject() -> CurrentValueSubject<Output, Failure> { | |
return (value as? CurrentValueSubject) ?? CurrentValueSubject(firstValue) | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment