3.
Example App: Koober
Written by René Cacheaux
This chapter introduces Koober, the example app used throughout this book. You’ll explore all the screens that comprise the app and how they work together. At the end of this chapter, you’ll take a quick tour of the Xcode project and source code. A reimplementation of Koober accompanies every chapter so you can compare and contrast different architectures. The material in this book assumes that you have a good understanding of the example app, so make sure to read this chapter before diving into any of the following chapters.
Koober
Imagine a world in which animals are human-like. They speak different languages, live in different countries, go to Mermaidbucks for coffee and so on. In this animal kingdom, smartphones have just hit the market for the first time. All the developers around the world race to build the next big app.
The kangaroo taxi industry in Australia is prime for disruption. Riders are tired of paying in cash and having to physically walk to the street to hail a kangaroo. Plus, some of the kangaroos have been hopping too high, making their passengers sick. Riders have no way to give feedback. A team of developers in Sydney noticed this and decided to launch a new startup company to build Koober, the next big ride-hailing app.
How Koober works
Koober works just like other ride-hailing apps that you might be familiar with from our own human world. Koober has the common components that make up a modern app such as onboarding, sign up, sign in, account profile, etc. Here’s a quick tour of all the screens, end to end.
Launching
You’ll see the launch screen when you first open the app. This screen comes and goes really quickly, so you might not see it. The app is determining if a user is signed in at the time this screen is presented.
Welcome
If a user is not signed in, the app transitions to the welcome screen.
Signing up
From the welcome screen, you can navigate to the sign-up screen to create a new user account.
Requesting a ride
Once you’re signed in, you’re taken to the pick-me-up app flow. First, the app determines your current physical location. The location is used as the ride’s pick-up location. Koober’s user location system always returns Sydney, Australia as your current location so you don’t have to give your actual location.
Next, you’re presented with a map that’s annotated with your pick-up location. At the top of the screen, there’s a Where to? button for navigating to the drop-off location picker.
The drop-off location picker is pre-seeded with locations. You can also perform a search using the UISearchBar
.
Once you pick a drop-off location, you’re taken back to the map screen wherein the drop-off location is annotated and the ride-option picker is presented at the bottom of the screen.
You use the ride-option picker to pick a ride option. A ride option specifies which kind of animal will pick you up. Some animals can carry more riders than others. For example, in Sydney, wallabies, wallaroos and kangaroos want to give rides for Koober.
Wallabies, wallaroos and kangaroos are considered different kinds of kangaroos. The three kinds of kangaroos range from smallest to largest in size, respectively.
This means that wallaroos can cary more weight than wallabies, and they are more expensive to ride.
As soon as you pick a ride option, you can confirm your new ride request. That’s how you request a ride with Koober.
Waiting for pick up
Once your new ride request is sent, the app takes you to the waiting-for-pick-up screen. You can start a new ride request from this screen by pressing the Start New Ride button.
Viewing your profile
You can view your user profile by tapping the Profile button located towards the top right-hand corner of all the pick-me-up flow screens.
Signing out
You can sign out of the app from the profile screen.
Signing in
After you sign out, the app presents the welcome screen wherein you can navigate to the sign-in screen. You can always sign in with johnny@gmail.com and password.
Why Koober?
When planning this book, we wanted to make sure that the example code would be applicable to real projects. We heard from the community that most architecture books oversimplify examples, leaving readers to figure out the real-world application of the theory. So we decided to build an entire app with the complexities of a real app to use as the basis for our examples. We really liked ride hailing because ride-hailing apps have all the complexity of a real-world app without an explosion of screens and UI to build.
Koober demonstrates architectural theory while incorporating aspects such as networking, persistence, authentication and more. We acknowledge this app doesn’t cover all of our readers’ type of projects; nevertheless, we hope everyone finds the material easy to incorporate into all kinds of projects.
If you try out any of this book’s techniques in your current projects, let us know how it goes! We’d love to hear from you in the book’s forum.
Getting started with the source
In order to familiarize yourself with the code in the sample app, this section walks you through how the app launches and where you can find the initial view controllers. This section uses the model–view–viewmodel (MVVM) version of the sample app. While following along, don’t worry too much about understanding the architecture as you’ll explore MVVM in Chapter 5.
Launch sequence
When launching Koober for the very first time, you’ll see two screens: the launch screen and the welcome screen.
The launch screen is implemented by LaunchViewController
and the welcome screen is implemented by WelcomeViewController
. Keep reading to see how these view controllers get onto the screen.
View controller hierarchy
Koober’s root view controller is implemented by MainViewController
, a custom container view controller.
When the app starts up, the MainViewController
is installed. MainViewController
loads by presenting the LaunchViewController
as a child view controller. When the launch screen is presented, the MainViewController
and LaunchViewController
make up the View Controller hierarchy.
The LaunchViewController
then determines whether a user is signed in or not. The first time you run Koober, a user will not be signed in, so the MainViewController
will navigate from the LaunchViewController
to the OnboardingViewController
.
OnboardingViewController
is a UINavigationController
subclass that starts by presenting the WelcomeViewController
. When the welcome screen is presented, the MainViewController
, OnboardingViewController
and WelcomeViewController
make up the View Controller hierarchy.
OK, time to fire up Xcode and take a peek at the source.
Opening the source
To view Koober’s source, find the 03-example-app/final/KooberApp directory and open KooberApp.xcodeproj. Each chapter has a different version of Koober found inside each chapter’s directory.
A single Xcode project contains all the source for Koober, and the source is organized into several targets.
Xcode project targets
- Koober: This is the iOS app target for Koober and contains the app delegate and other app-specific resources, such as the info.plist. Other than the app delegate, this target does not contain any source.
- Koober_iOS: This Cocoa Touch Framework contains all the UI code specific to the Koober iOS app, such as view controllers and views.
-
KooberUIKit: This Cocoa Touch Framework contains code that depends on
UIKit
and that could be used on otherUIKit
platforms such astvOS
. -
KooberKit: This last Cocoa Touch Framework contains code that does not depend on
UIKit
. Therefore, this framework can be used in any Apple platform.
Presenting MainViewController
To get started tracing the launch sequence in code, inside Xcode’s Project navigator, open Koober/AppDelegate.swift. On the first line of application(_:didFinishLaunchingWithOptions:)
, the MainViewController
is instantiated by the injectionContainer
.
The injectionContainer
is a factory that creates instances of objects with their dependencies. In this case, the injectionContainer
allows the app delegate to create a new instance of MainViewController
without knowing what other objects MainViewController
needs in order to be instantiated.
On line 45, the MainViewController
is set as the window
’s root view controller. So that’s how the MainViewController
makes its way to the screen.
Presenting the launch screen
Next, open Koober_iOS/iOSApp/MainViewController.swift. You are now in the Koober_iOS framework target where all the view controller code lives. On line 136, inside the viewDidLoad
method, MainViewController
subscribes to MainViewModel
updates.
Open KooberKit/UILayer/MainViewModel.swift. You are now in the KooberKit framework target.
On line 35, the view model’s @Published
view
property is initialized with a .launching
MainView
enum case.
Because of the initial .launching
value, when MainViewController
subscribes to the ‘view’ property’s publisher on viewDidLoad
, the view model will publish the .launching
value to the MainViewController
.
Return to Koober_iOS/iOSApp/MainViewController.swift.
Whenever a new value is published, the subscription to the view model calls the present(_:)
method on line 70. Because the first value published is .launching
, the presentLaunching
method is called inside present(_:)
, right after MainViewController
loads. The presentLaunching
method on line 94 adds the LaunchViewController
as a child to MainViewController
, presenting the launch screen.
Getting from launch to onboarding
Make your way to Koober_iOS/iOSApp/LaunchViewController.swift.
On line 47, during loadView
, LaunchViewController
’s root view is created with a LaunchViewModel
.
Go the root view by opening Koober_iOS/iOSApp/LaunchRootView.swift. During initialization, on line 45, the launch view asks the view model to attempt to load a user session to see if a user is signed in.
Open the LaunchViewModel
’s source located at KooberKit/UILayer/LaunchViewModel.swift.
You can find the loadUserSession
method on line 56. Once this method finishes querying for a user session, goToNextScreen(userSession:)
is called.
When you first run Koober, there won’t be a signed-in user so the goToNextScreen(userSession:)
method will be called with nil
. When goToNextScreen(userSession:)
determines that a user is not signed in, on line 82 and 83, the notSignedInResponder
’s notSignedIn
method is called.
Next, open KooberKit/UILayer/MainViewModel.swift. Notice that this view model conforms to the NotSignedInResponder
protocol.
Once LaunchViewModel
determines a user is not logged in, LaunchViewModel
calls MainViewModel
’s notSignedIn
method via the NotSignedInResponder
protocol. In other words, MainViewModel
is LaunchViewModel
’s notSignedInResponder
. You can read more about this MVVM setup in Chapter 5.
On line 41, inside notSignedIn
, notice how MainViewModel
updates the view
property with a new MainView
enum case value, .onboarding
. Since MainViewController
is subscribed to view
’s publisher, this update publishes the new .onboarding
value and tells MainViewController
to transition from it’s current presentation to presenting OnboardingViewController
. The transition happens in MainViewController
’s presentOnboarding
method.
Presenting the Welcome screen
Now that OnboardingViewController
is on screen, how does WelcomeViewController
get presented?
Open Koober_iOS/iOSApp/Onboarding/OnboardingViewController.swift.
OnboardingViewController
loads the same way MainViewController
loads via view model subscription. On line 63, during viewDidLoad
, OnboardingViewController
subscribes to the OnboardingViewModel
’s $navigationAction
publisher.
There’s some extra complexities in OnboardingViewController
that you don’t need to worry about just yet. The complexity exists because OnboardingViewController
is a UINavigationController
, you can read more about this in Chapter 5. The main gist is that right after OnboardingViewController
loads, presentWelcome
is called on line 88. This is how the welcome screen gets presented.
Alright! Now that you’re familiar with Koober’s source code, you’ll have no problem following along with the example code in rest of the chapters.
Key points
- Koober, a kangaroo ride-hailing app, is the example app used throughout this book.
- Koober incorporates many of the complexities found in real-world apps, such as authentication and navigation.
- A complete re-implementation of Koober accompanies each architecture chapter.
- The Koober Xcode project consists of four targets: Koober, Koober_iOS, KooberUIKit and KooberKit.
-
MainViewController
,LaunchViewController
andOnboardingViewController
coordinate in order to launch Koober.