-
-
Save jasdev/b03a492f413d6da1f50bb6758870edbe to your computer and use it in GitHub Desktop.
`RandomNumberViewModel` sketch.
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
final class RandomNumberViewModel: ObservableObject { | |
private var subscriptions = Set<AnyCancellable>() | |
// MARK: - Inputs | |
let randomNumberPing = PassthroughSubject<Void, Never>() /// (1) `randomNumberPing` would | |
/// receive `send()` calls from a `Button`’s `action` closure. | |
// MARK: - Outputs | |
@Published var randomNumber: Int? /// (2) On the output side, `randomNumber` could power a modal that | |
/// displays the returned value. | |
init() { | |
randomNumberPing | |
.setFailureType(to: RandomDotOrgError.self) /// (3) To line up our subject’s error with `randomNumberPublisher`’s. | |
/// I have some [more detailed writing](https://jasdev.me/set-output-type) on `.setFailureType(to:)`, for the curious. | |
.map(randomNumberPublisher) | |
.switchToLatest() /// (4) Switching to latest here cancels any in-flight requests. | |
.print() /// (5) To help with downstream debugging. | |
.receive(on: DispatchQueue.main) /// (6) Generally, we’ll need to dispatch to the main queue when exposing outputs to views. | |
.assign(to: \.randomNumber, onWeak: self) | |
.store(in: &subscriptions) | |
} | |
} | |
// MARK: - Helpers | |
extension Publisher where Failure == Never { | |
func assign<Root: AnyObject>( /// (7) A `weak` analog to | |
/// [`Publisher.assign(to:on:)`](https://developer.apple.com/documentation/combine/publisher/3235801-assign). | |
/// This operator is helpful in scenarios like the above where we’re piping a sequence to a `@Published` | |
/// property on the containing instance and need to avoid a retain cycle. | |
/// | |
/// Additional notes: https://jasdev.me/notes/weak-assignment. | |
to keyPath: ReferenceWritableKeyPath<Root, Output>, | |
onWeak object: Root | |
) -> AnyCancellable { | |
sink { [weak object] value in | |
object?[keyPath: keyPath] = value | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment