Skip to content

Instantly share code, notes, and snippets.

@velyan
Last active March 4, 2020 18:31
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save velyan/c1e20503ae82954d77fd451bc18f6490 to your computer and use it in GitHub Desktop.
Save velyan/c1e20503ae82954d77fd451bc18f6490 to your computer and use it in GitHub Desktop.
Swift State Pattern
import UIKit
protocol Stateful {
func loggedIn()
func loggedOut()
}
extension UIViewController: Stateful {
func loggedIn() {
navigationItem.loggedIn()
}
func loggedOut() {
navigationItem.loggedOut()
}
}
extension UINavigationItem: Stateful {
func loggedIn() {
rightBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: nil, action: nil)
}
func loggedOut() {
rightBarButtonItem = UIBarButtonItem(title: "Login", style: .plain, target: nil, action: nil)
}
}
import Foundation
fileprivate protocol Statelike {
var stateMachine: StateMachine { get }
func logIn()
func logOut()
}
extension Statelike {
func logIn() {}
func logOut() {}
}
fileprivate struct LoggedIn: Statelike {
var stateMachine: StateMachine
func logOut() {
stateMachine.setState(LoggedOut(stateMachine: stateMachine))
stateMachine.loggedOut?()
}
}
fileprivate struct LoggedOut: Statelike {
var stateMachine: StateMachine
func logIn() {
stateMachine.setState(LoggedIn(stateMachine: stateMachine))
stateMachine.loggedIn?()
}
}
class StateMachine {
typealias StateHandler = () -> ()
var loggedIn: StateHandler?
var loggedOut: StateHandler?
private lazy var state: Statelike = {
return LoggedOut(stateMachine: self)
}()
@objc func logIn() {
state.logIn()
}
@objc func logOut() {
state.logOut()
}
fileprivate func setState(_ state: Statelike) {
self.state = state
}
}
import UIKit
extension UIBarButtonItem {
func addTarget(_ target: AnyObject?, action: Selector){
self.target = target
self.action = action
}
}
extension ViewController {
override func loggedIn() {
super.loggedIn()
self.navigationItem.rightBarButtonItem?.addTarget(self.stateMachine, action: #selector(StateMachine.logOut))
}
override func loggedOut() {
super.loggedOut()
self.navigationItem.rightBarButtonItem?.addTarget(self.stateMachine, action: #selector(StateMachine.logIn))
}
}
class ViewController: UIViewController {
var stateMachine = StateMachine()
override func viewDidLoad() {
super.viewDidLoad()
stateMachine.loggedIn = { self.loggedIn() }
stateMachine.loggedOut = { self.loggedOut() }
stateMachine.logIn()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment