Skip to content

Instantly share code, notes, and snippets.

@danielt1263
Created March 30, 2019 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielt1263/82eb5333b5da068dfdf330d4011d3edd to your computer and use it in GitHub Desktop.
Save danielt1263/82eb5333b5da068dfdf330d4011d3edd to your computer and use it in GitHub Desktop.
A simplified RxFlow system
//
// Coordinator.swift
// RxFlow
//
// Created by Daniel Tartaglia on 2/13/19.
// Copyright © 2019 Daniel Tartaglia. MIT License.
//
import Foundation
import RxSwift
public protocol CoordinatorType {
associatedtype Step
func navigate(to step: Step) -> [Starter]
func asCoordinator() -> Coordinator<Step>
}
extension CoordinatorType {
public func asCoordinator() -> Coordinator<Step> {
return Coordinator(self.navigate(to:))
}
}
public final class Coordinator<Step>: CoordinatorType {
private let navigate: (Step) -> [Starter]
public init(_ navigator: @escaping (Step) -> [Starter]) {
navigate = navigator
}
public func navigate(to step: Step) -> [Starter] {
return navigate(step)
}
}
//
// Flow.swift
// RxFlow
//
// Created by Daniel Tartaglia on 2/17/19. MIT License
//
import Foundation
import RxSwift
public typealias Starter = () -> Void
public func flow<C: CoordinatorType, Step>(coordinator: C, presentable: Presentable, step: Step) -> Starter where C.Step == Step {
let stepper = presentable.rxVisible
.filter { $0 }
.map { _ in step }
return flow(coordinator: coordinator.asCoordinator(), presentable: presentable, stepper: stepper)
}
public func flow<C: CoordinatorType, Step>(coordinator: C, presentable: Presentable, oneStep: Step) -> Starter where C.Step == Step {
let stepper = presentable.rxVisible
.filter { $0 }
.map { _ in oneStep }
.take(1)
return flow(coordinator: coordinator.asCoordinator(), presentable: presentable, stepper: stepper)
}
public func flow<C: CoordinatorType, O: ObservableConvertibleType>(coordinator: C, presentable: Presentable, stepper: O) -> Starter where C.Step == O.E {
return {
let coordinator = coordinator
_ = stepper
.asObservable()
.stallUnless(presentable.rxVisible)
.takeUntil(presentable.rxDismissed.asObservable())
.observeOn(MainScheduler.instance)
.subscribe(onNext: { step in
let results = coordinator.navigate(to: step)
for each in results {
each()
}
})
}
}
//
// Presentable.swift
// RxFlow
//
// Created by Daniel Tartaglia on 2/13/19.
// Copyright © 2019 Daniel Tartaglia. MIT License.
//
import UIKit
import RxSwift
import RxCocoa
public protocol Presentable {
var rxVisible: Observable<Bool> { get }
var rxDismissed: Maybe<Void> { get }
}
extension UIWindow: Presentable {
public var rxVisible: Observable<Bool> {
return self.rx.sentMessage(#selector(UIWindow.makeKeyAndVisible)).map { _ in true }
}
public var rxDismissed: Maybe<Void> {
return Maybe.never()
}
}
extension UIViewController: Presentable {
public var rxVisible: Observable<Bool> {
let viewDidAppear = self.rx.sentMessage(#selector(UIViewController.viewDidAppear)).map { _ in true }
let viewWillDisappear = self.rx.sentMessage(#selector(UIViewController.viewWillDisappear)).map { _ in false }
return Observable.merge(viewDidAppear, viewWillDisappear).startWith(viewIfLoaded?.window != nil)
}
public var rxDismissed: Maybe<Void> {
return self.rx.deallocating
.take(1)
.asMaybe()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment