Skip to content

Instantly share code, notes, and snippets.

@RoyalIcing
Last active February 13, 2018 16:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save RoyalIcing/fa36f3737fcfae0703c5df7c7831ed8f to your computer and use it in GitHub Desktop.
Save RoyalIcing/fa36f3737fcfae0703c5df7c7831ed8f to your computer and use it in GitHub Desktop.
Responder chain in Swift using enums
//: 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