Skip to content

Instantly share code, notes, and snippets.

@siejkowski
Last active June 6, 2016 08:36
Show Gist options
  • Save siejkowski/6c1d9aee7c6353f7d5138df21a6596db to your computer and use it in GitHub Desktop.
Save siejkowski/6c1d9aee7c6353f7d5138df21a6596db to your computer and use it in GitHub Desktop.
play with vc hierarchy
import UIKit
protocol Action {}
struct ConcreteAction1 : Action {}
struct ConcreteAction2 : Action {}
enum ActionError : ErrorType {
case NoHandler
}
protocol UIViewControllerActionHandler : class {
func handleAction(action: Action) -> Bool
}
extension UIViewController {
func handlerOfType<T>(type: T.Type) -> T {
var tmp : UIViewController? = self
while let viewController = tmp {
if let handlerCandidate = viewController as? T {
return handlerCandidate
}
tmp = viewController.parentViewController
}
fatalError()
}
func emitAction(action: Action) {
var tmp : UIViewController? = self
while let viewController = tmp {
if let handlerCandidate = viewController as? UIViewControllerActionHandler
where handlerCandidate.handleAction(action) {
return
}
tmp = viewController.parentViewController
}
fatalError()
}
}
protocol ConcreteAction1Handler : class, UIViewControllerActionHandler {
func handleAction(action: ConcreteAction1) -> Bool
}
protocol ConcreteAction2Handler : class, UIViewControllerActionHandler {
func handleAction(action: ConcreteAction2) -> Bool
}
class ContentController : UIViewController {
init(_ handler1: ConcreteAction1Handler, _ handler2: ConcreteAction2Handler) {
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class RootFlowController : UIViewController {}
extension RootFlowController : ConcreteAction1Handler {
func handleAction(action: ConcreteAction1) -> Bool {
print("action1 handled")
return true
}
func handleAction(action: Action) -> Bool {
if let ca = action as? ConcreteAction1 { return handleAction(ca) }
return false
}
func returnFlowController() -> FlowController {
let flowController = FlowController(
self.handlerOfType(ConcreteAction1Handler)
)
self.addChildViewController(flowController)
flowController.didMoveToParentViewController(self)
return flowController
}
}
class FlowController : UIViewController {
init(_ handler: ConcreteAction1Handler) {
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
func returnContentController() -> ContentController {
let concreteController = ContentController(
self.handlerOfType(ConcreteAction1Handler),
self.handlerOfType(ConcreteAction2Handler)
)
self.addChildViewController(concreteController)
concreteController.didMoveToParentViewController(self)
return concreteController
}
}
extension FlowController : ConcreteAction2Handler {
func handleAction(action: ConcreteAction2) -> Bool {
print("action2 handled")
return true
}
func handleAction(action: Action) -> Bool {
if let action = action as? ConcreteAction2 { return handleAction(action) }
return false
}
}
let rootFlowController = RootFlowController()
let flowController = rootFlowController.returnFlowController()
let concreteController = flowController.returnContentController()
concreteController.emitAction(ConcreteAction1())
concreteController.emitAction(ConcreteAction2())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment