Last active
February 13, 2018 16:05
-
-
Save RoyalIcing/fa36f3737fcfae0703c5df7c7831ed8f to your computer and use it in GitHub Desktop.
Responder chain in Swift using enums
This file contains hidden or 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
//: Responder chain in Swift using enums | |
protocol CommandProtocol {} | |
protocol Responder: class { | |
var nextResponder: Responder? { get } | |
func performerForCommand | |
<Command : CommandProtocol> | |
(command: Command) -> (() -> ())? | |
func noResponderForCommand | |
<Command : CommandProtocol> | |
(command: Command) | |
func performCommand | |
<Command : CommandProtocol> | |
(command: Command) -> Bool | |
} | |
extension Responder { | |
func noResponderForCommand | |
<Command : CommandProtocol> | |
(command: Command) { | |
print("Beep") | |
} | |
func performCommand | |
<Command : CommandProtocol> | |
(command: Command) -> Bool { | |
if let performer = performerForCommand(command) { | |
performer() | |
return true | |
} | |
else { | |
noResponderForCommand(command) | |
return false | |
} | |
} | |
} | |
enum PasteboardCommand : CommandProtocol { | |
case copy | |
case cut | |
} | |
enum WindowCommand : CommandProtocol { | |
case minimize | |
case close | |
} | |
class View : Responder { | |
weak var nextResponder: Responder? | |
func performerForCommand | |
<Command : CommandProtocol> | |
(command: Command) -> (() -> ())? { | |
return nextResponder?.performerForCommand(command) | |
} | |
} | |
class MyView : View { | |
override func performerForCommand | |
<Command : CommandProtocol> | |
(command: Command) -> (() -> ())? { | |
if let command = command as? PasteboardCommand { | |
switch command { | |
case .copy: return copy | |
case .cut: return cut | |
} | |
} | |
return super.performerForCommand(command) | |
} | |
func copy() { | |
print("Copy") | |
} | |
func cut() { | |
print("Cut") | |
} | |
} | |
class Window : Responder { | |
weak var nextResponder: Responder? | |
var contentView: View? { | |
didSet { | |
contentView?.nextResponder = self | |
} | |
} | |
func performerForCommand | |
<Command : CommandProtocol> | |
(command: Command) -> (() -> ())? { | |
if let command = command as? WindowCommand { | |
switch command { | |
case .minimize: return minimize | |
case .close: return close | |
} | |
} | |
return nextResponder?.performerForCommand(command) | |
} | |
func minimize() { | |
print("Minimize") | |
} | |
func close() { | |
print("Close") | |
} | |
} | |
var view = MyView() | |
var window = Window() | |
window.contentView = view | |
let copyResponder = view.performerForCommand(PasteboardCommand.copy) | |
let respondsToCopy = copyResponder != nil | |
// view copy | |
view.performCommand(PasteboardCommand.copy) // true | |
// view minimize | |
view.performCommand(WindowCommand.minimize) // true | |
// window cut | |
window.performCommand(PasteboardCommand.cut) // false | |
// window close | |
window.performCommand(WindowCommand.close) // true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment