Created
December 12, 2022 21:09
-
-
Save cristhianleonli/2a9265de31038bc1e7a77503c0a03496 to your computer and use it in GitHub Desktop.
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
// | |
// ReactiveViewModel.swift | |
// MVRxVM | |
// | |
// Created by Cristhian Leon on 2022. | |
// | |
import Foundation | |
import Combine | |
protocol ReactiveViewModel { | |
/// Makes reference to any view state the view model uses. | |
associatedtype ViewState | |
/// Since Swift still doens't support wrappingProperties in protocols, | |
/// this property is required to implement. This won't affect the behavior, | |
/// rather just satisfies the compiler. | |
var viewState: Published<ViewState>.Publisher { get } | |
/// Allows view models be able to map the state into properties, | |
/// remove duplicates, and receive events on the main queue. | |
/// This is to force view to run on sink on UI queues. | |
func stateOf<T: Equatable>(_ transform: @escaping (ViewState) -> T) -> AnyPublisher<T, Never> | |
} | |
extension ReactiveViewModel { | |
func stateOf<T: Equatable>(_ transform: @escaping (ViewState) -> T) -> AnyPublisher<T, Never> { | |
viewState | |
// convert the whole state into a property of it. | |
.map(transform) | |
// Avoids the view to react multiple times when the value hasn't changed. | |
.removeDuplicates() | |
// since this is called ONLY from the UI, receveing on main queue is required. | |
.receive(on: DispatchQueue.main) | |
// convert it to any. | |
.eraseToAnyPublisher() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment