Skip to content

Instantly share code, notes, and snippets.

@illescasDaniel
Created February 24, 2020 20:27
Show Gist options
  • Select an option

  • Save illescasDaniel/1931a9114c800ed13ad3d7ccda68d7f4 to your computer and use it in GitHub Desktop.

Select an option

Save illescasDaniel/1931a9114c800ed13ad3d7ccda68d7f4 to your computer and use it in GitHub Desktop.
GKStateMachine test example
import Foundation
import GameplayKit
protocol TestStatesDelegate: class {
func onFetch()
func onSuccess()
func onError()
}
enum DataFetchState {
class Idle: GKState {
weak var delegate: TestStatesDelegate?
init(delegate: TestStatesDelegate) {
self.delegate = delegate
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is Fetching.Type
}
override func didEnter(from previousState: GKState?) {
print("doing nothing")
}
}
class Fetching: GKState {
weak var delegate: TestStatesDelegate?
init(delegate: TestStatesDelegate) {
self.delegate = delegate
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is Failure.Type || stateClass is Success.Type
}
override func didEnter(from previousState: GKState?) {
delegate?.onFetch()
}
}
class Failure: GKState {
weak var delegate: TestStatesDelegate?
var error: Error? {
didSet {
self.stateMachine?.enter(DataFetchState.Failure.self)
}
}
init(delegate: TestStatesDelegate) {
self.delegate = delegate
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is Idle.Type || stateClass is Reload.Type
}
override func didEnter(from previousState: GKState?) {
delegate?.onError()
stateMachine?.enter(DataFetchState.Reload.self)
}
}
class Success: GKState {
weak var delegate: TestStatesDelegate?
var data: [Person] = [] {
didSet {
self.stateMachine?.enter(DataFetchState.Success.self)
}
}
init(delegate: TestStatesDelegate) {
self.delegate = delegate
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is Idle.Type || stateClass is Reload.Type
}
override func didEnter(from previousState: GKState?) {
delegate?.onSuccess()
}
}
class Reload: GKState {
weak var delegate: TestStatesDelegate?
private var retryTimes = 0
private var maxRetryTimes = 5
init(delegate: TestStatesDelegate) {
self.delegate = delegate
}
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return stateClass is Fetching.Type || stateClass is Idle.Type
}
override func didEnter(from previousState: GKState?) {
print("will reload")
retryTimes += 1
guard retryTimes < self.maxRetryTimes else {
print("x - Maximum retry times")
stateMachine?.enter(DataFetchState.Idle.self)
return
}
stateMachine?.enter(DataFetchState.Fetching.self)
}
}
}
//
struct Person {
var name: String
}
class TestVC {
private lazy var idle = DataFetchState.Idle(delegate: self)
private lazy var fetching = DataFetchState.Fetching(delegate: self)
private lazy var failure = DataFetchState.Failure(delegate: self)
private lazy var success = DataFetchState.Success(delegate: self)
private lazy var reload = DataFetchState.Reload(delegate: self)
private(set) lazy var stateMachine = GKStateMachine(states: [idle, fetching, failure, success, reload])
init() {
self.stateMachine.enter(DataFetchState.Fetching.self)
}
}
extension TestVC: TestStatesDelegate {
enum Errors: Error {
case something
}
func onFetch() {
print("fetching stuff")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
print("-----")
if Bool.random() { // I got the data
self.success.data = [Person(name: "Daniel"), Person(name: "Pepe")]
} else {
self.failure.error = Errors.something
}
}
}
func onError() {
print("failed fetching")
print(self.failure.error ?? "")
}
func onSuccess() {
print("success fetching")
print(self.success.data)
}
}
let vc = TestVC()
//
RunLoop.main.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment