Last active
May 18, 2017 08:51
-
-
Save feighter09/0a1af792344782ff5d3f to your computer and use it in GitHub Desktop.
Functional View Controllers from Chris Eidhof's talk @ FunSwiftConf 2015
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
import UIKit | |
// MARK: - Building Blocks | |
struct Screen<A> { | |
let run: (A -> Void) -> UIViewController | |
} | |
extension Screen { | |
func map<B>(f: A -> B) -> Screen<B> | |
{ | |
return Screen<B> { onComplete in | |
return self.run { a in | |
onComplete(f(a)) | |
} | |
} | |
} | |
} | |
struct Flow<A> { | |
let build: (naviagationController: UINavigationController, onComplete: A -> Void) -> UIViewController | |
private init(build: (naviagationController: UINavigationController, onComplete: A -> Void) -> UIViewController) | |
{ | |
self.build = build | |
} | |
} | |
extension Flow { | |
init(screen: Screen<A>) | |
{ | |
build = { nav, onComplete in | |
let vc = screen.run(onComplete) | |
nav.pushViewController(vc, animated: true) | |
return nav | |
} | |
} | |
func run(navigationController: UINavigationController = UINavigationController(), | |
onComplete: A -> Void = { _ in }) -> UIViewController | |
{ | |
build(naviagationController: navigationController, onComplete: onComplete) | |
return navigationController | |
} | |
func flatMap<B>(f: A -> Flow<B>) -> Flow<B> | |
{ | |
return Flow<B>(build: { (navigationController, onComplete) -> UIViewController in | |
return self.build(naviagationController: navigationController, onComplete: { a in | |
f(a).build(naviagationController: navigationController, onComplete: onComplete) | |
}) | |
}) | |
} | |
func push<B>(f: A -> Screen<B>) -> Flow<B> | |
{ | |
return flatMap { a in Flow<B>(screen: f(a)) } | |
} | |
} | |
// MARK: - Use | |
infix operator >>> { associativity left } | |
func >>> <A, B>(flow: Flow<A>, f: A -> Screen<B>) -> Flow<B> | |
{ | |
return flow.push(f) | |
} | |
func >>> <A, B>(flow: Flow<A>, f: A -> Flow<B>) -> Flow<B> | |
{ | |
return flow.flatMap(f) | |
} | |
protocol Screenable { | |
typealias A | |
typealias B | |
static func screen(initData: A) -> Screen<B> | |
init(initData: A, onComplete: B -> Void) | |
var onComplete: B -> Void { get } | |
} | |
extension Screenable { | |
static func screen(initData: Self.A) -> Screen<B> | |
{ | |
return Screen<B> { onComplete in | |
Self(initData: initData, onComplete: onComplete) as! UIViewController | |
} | |
} | |
} | |
extension Screenable where A == Void { | |
static func screen() -> Screen<B> | |
{ | |
return Screen<B> { onComplete in | |
Self(initData: Void(), onComplete: onComplete) as! UIViewController | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment