Mastering App Development and UIAccessibility with Swift: Adventure application

0 of 13 lessons complete (0%)

The AppCoordinator pattern for routing between screens

The AppCoordinator pattern for routing between screens

The iOS Accessibility Handbook

We will use the AppCoordinator Pattern for two main purposes:

– extract the responsibility to present view controller into dedicated one
– present Voice Over alert screen whenever the user deactivates VoiceOver (we do not want to duplicate code in all of our game levels)

See https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps for more info on the App Coordinator pattern.

The AppCoordinator class will handle all presenting methods thus it will implement the following protocol methods:

First, the player progress are loaded in the AppDelegate, the game flow is passed to the app coordinator which is registered as the game flow delegate:

Through the initializer we use dependency injection to inject the Game Flow and other external dependencies:

If this is the first time the app is being launched, we go to the intro screen else we route to the correct chapter screen through the game flow component:

Each routing method to launch each level is configured based on the received level obtained from the Game Flow.

The iOS Accessibility Handbook

We allow the game levels to ask for level answer validation through the validateChapter and validateAnswers app coordinator methods:

The Game Flow handles the internal level sequencing logic and triggers back the routeToChapter, routeToLevel, routeToResults methods (see Router protocol).

extension AppCoordinator { func validateChapter() {

gameFlow.validateChapter() }

func validate(_ answers: [String]) { gameFlow.validate(answers)

} }

extension AppCoordinator: Router {
func routeToChapter(_ chapter: Chapter, isNewChapter: Bool) {

if isNewChapter {
userDefaults.set(chapter.index, forKey: UserDefaultsKeys.currentChapterIndex.rawValue) userDefaults.set(0, forKey: UserDefaultsKeys.currentLevelIndex.rawValue)

}

presentChapterController(chapter) }

func routeToLevel(_ level: Level) {
let currentLevel = gameFlow.getCurrentLevelIndex()
userDefaults.set(currentLevel, forKey: UserDefaultsKeys.currentLevelIndex.rawValue)

switch level {
case is ClosedQuestionLevel:

presentClosedQuestionController(level) case is OpenQuestionLevel:

presentOpenQuestionController(level) case is RotorLevel:

presentRotorQuestionController(level) case is SearchLevel:

presentSearchQuestionController(level) default:

break }

}

func routeToResults() { self.presentIntroController(.gameEnd)

} }

We have seen all the core logic of the app, we can now take a closer look on each of the main UIAccessibility framework capabilities,

Each level we will design in the next chapters is focussed on one key feature, feel free to refer the the related documentations for further details:
– Closed & Open Questions Levels: for the general concepts https://developer.apple.com/

documentation/uikit/accessibility/uiaccessibility.
– Rotor Based Levels: https://developer.apple.com/documentation/uikit/uiaccessibilitycustomrotor – Custom Actions Based Levels: https://developer.apple.com/documentation/uikit/

uiaccessibilitycustomaction

en_USEnglish