Last active
June 6, 2016 08:36
-
-
Save siejkowski/6c1d9aee7c6353f7d5138df21a6596db to your computer and use it in GitHub Desktop.
play with vc hierarchy
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 | |
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