Chapters

Hide chapters

Advanced iOS App Architecture

Fourth Edition · iOS 15 · Swift 5.5 · Xcode 13.2

Before You Begin

Section 0: 4 chapters
Show chapters Hide chapters

Section I

Section 1: 9 chapters
Show chapters Hide chapters

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.
  • KooberiOS: This Swift Package contains all the UI code specific to the Koober iOS app, such as view controllers and views.
  • KooberUIKit: This Swift Package contains code that depends on UIKit and that could be used on other UIKit platforms such as tvOS.
  • KooberKit: This last Swift Package contains code that does not depend on UIKit. Therefore, this package 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 KooberiOS/Sources/KooberiOS/iOSApp/MainViewController.swift. You are now in the KooberiOS Swift Package where all the view controller code lives. On line 136, inside the viewDidLoad method, MainViewController subscribes to MainViewModel updates.

Open KooberKit/Sources/KooberKit/UILayer/MainViewModel.swift. You are now in the KooberKit package.

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 KooberiOS/Sources/KooberiOS/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 KooberiOS/Sources/KooberiOS/iOSApp/LaunchViewController.swift.

On line 47, during loadView, LaunchViewController’s root view is created with a LaunchViewModel.

Go the root view by opening KooberiOS/Sources/KooberiOS/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/Sources/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/Sources/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 KooberiOS/Sources/KooberiOS/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 and OnboardingViewController coordinate in order to launch Koober.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.