Skip to content

Instantly share code, notes, and snippets.

@seivan
Forked from RoyalIcing/responder-chain.swift
Created June 2, 2016 07:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seivan/67ef734ec2ec6481179b4ecddea2cc5e to your computer and use it in GitHub Desktop.
Save seivan/67ef734ec2ec6481179b4ecddea2cc5e 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