Get a taste. This example shows using finite state machine to App Page management. It incudes reduce func to transit state, error handling for transition failure and backup plan.
import SwiftUI
struct Episode { }
struct Level { }
enum State {
case introduction // On the first page of the game
case help // In the help screen
case choosingEpisode // Choosing an episode
case choosingLevel(Episode) // After choosing an episode, player is now choosing
// a level
case playingLevel(Episode, Level) // Now playing the chosen level
case finishedLevel(Episode, Level, Int) // Finished a level, displaying their
// score.
}
enum Event {
case displayHelp // Takes the user from the intro to the help screen.
case dismissHelp // Takes the user back to the intro from help.
case startPlaying // Takes the user from the intro to the episode chooser.
case chooseEpisode(Episode) // The user selected an episode, so take
// the user from the episode chooser to the level chooser.
case chooseLevel(Level) // The user selected a level, so take the user
// from the level chooser to the gameplay.
case completeLevel(Int) // Takes the user from gameplay to the completed
// level screen, displaying their achieved score.
case dismissFinishedLevel // Takes the user from the completed level
// screen back to the level chooser to play again.
}
class FiniteStateMachine {
/// singleton
static let shared = FiniteStateMachine()
///. initial state
var state = State.introduction
/// This selects the appropriate transition to handle the event.
/// The choice of transition may depend upon the old state.
func reduce(event: Event) throws -> State {
switch (state, event) {
case (.introduction, .displayHelp):
return presentHelp()
case (.help, .dismissHelp):
return dismissHelp()
case (.introduction, .startPlaying):
return presentEpisodeChooser()
case (.choosingEpisode, .chooseEpisode(let episode)):
return presentLevelChooser(episode: episode)
case (.choosingLevel(let episode), .chooseLevel(let level)):
return presentGamePlay(level: level)
default:
throw MyErrors.transitionNotFound
}
}
enum MyErrors: Error {
case transitionNotFound
}
func presentHelp() -> State {
return State.help
}
func dismissHelp() -> State {
// ?
return State.introduction
}
func presentEpisodeChooser() -> State {
return State.choosingEpisode
}
func presentGamePlay(level: Level) -> State {
return State.playingLevel(Episode(), Level())
}
func presentLevelChooser(episode: Episode) -> State {
// let levelChooser = ...create level chooser view controller...
// levelChooser.levels = episode.levels
// NavigationManager.shared.rootNavController
// .pushViewController(levelChooser, animated: true)
// Return the new state
return State.choosingLevel(episode)
}
}