Chapters

Hide chapters

iOS Apprentice

Eighth Edition · iOS 13 · Swift 5.2 · Xcode 11

My Locations

Section 4: 11 chapters
Show chapters Hide chapters

Store Search

Section 5: 13 chapters
Show chapters Hide chapters

15. UIKit and The One-Button App
Written by Eli Ganim

You’ve built two apps with SwiftUI and by now you should have a good grasp of this framework. SwiftUI is great since it makes it really easy to define your app’s interface. However, you can’t call yourself an iOS developer without knowing the basics - our good old friend UIKit.

UIKit is an alternative way to build the UI of your app. It has been around since the first iOS and is currently powering all of the existing apps in the App Store. Actually, it’s the foundation on which SwiftUI is built.

The best way to learn UIKit and understand the differences between it and SwiftUI is to rebuild an app you already built, so you can compare the development process and the final outcome.

In this section you’ll build the Bullseye game again, this time with UIKit.

This chapter covers the following:

  • The Bullseye game: A reminder of the game you already built in Section 1.
  • The one-button app: Creating a simple one-button app in which the button can take an action based on a tap on the button.
  • The anatomy of an app: A brief explanation as to the inner-workings of an app.

The Bullseye game

As a reminder, this is what the Bullseye game will look like when you’re finished:

The finished Bullseye game
The finished Bullseye game

As you probably remember, the objective of the game is to put the bullseye, which is on a slider that goes from 1 to 100, as close to a randomly chosen target value as you can. In the screenshot above, the aim is to put the bullseye at 84. Because you can’t see the current value of the slider, you’ll have to “eyeball” it.

When you’re confident of your estimate, you press the “Hit Me!” button and a pop-up will tell you what your score is. The closer to the target value you are, the more points you score. After you dismiss the alert pop-up, a new round begins with a new random target. The game repeats until the player presses the “Start Over” button, which resets the score to 0.

Making a programming to-do list

Just like in Section 1, you’ll follow this to-do list to get the job done:

  • Put a button on the screen and label it “Hit Me!”

  • When the player presses the Hit Me! button, the app has to show an alert pop-up to inform the player how well he or she did. Somehow, you have to calculate the score and put that into this alert.

  • Put text on the screen, such as the “Score:” and “Round:” labels. Some of this text changes over time; for example, the score, which increases when the player scores points.

  • Put a slider on the screen with a range between the values 1 and 100.

  • Read the value of the slider after the user presses the Hit Me! button.

  • Generate a random number at the start of each round and display it on the screen. This is the target value.

  • Compare the value of the slider to that random number and calculate a score based on how far off the player is. You show this score in the alert pop-up.

  • Put the Start Over button on the screen. Make it reset the score and put the player back to the first round.

  • Put the app in landscape orientation.

  • Make it look pretty.

The one-button app

Start at the top of the list and make an extremely simple first version of the game that just displays a single button. When you press the button, the app pops up an alert message. That’s all you are going to do for now. Once you have this working, you can build the rest of the game on this foundation.

The app will look like this:

The app contains a single button (left) that shows an alert when pressed (right)
The app contains a single button (left) that shows an alert when pressed (right)

Creating a new project

➤ Launch Xcode.

➤ Choose Create a new Xcode project.

➤ Select Single View Application and press Next.

➤ Fill out these options as follows:

  • Product Name: Bullseye.

  • Team: None or your team.

  • Organization Name: Your name or the name of your company.

  • Organization Identifier: Your own identifier in reverse domain notation.

  • Language: Swift

  • Make sure the three options at the bottom — Use Core Data, Include Unit Tests, and Include UI Tests — are not selected. You won’t use those in this project.

  • Most importantly: Uncheck the Use SwiftUI checkbox! This is how you tell Xcode you’re going to create a UIKit based app.

➤ Press Next.

You can ignore the “Create Git repository on My Mac” checkbox for now. You’ll learn about the Git version control system later on.

➤ Press Create to finish.

When it is done, the screen should look something like this:

The main Xcode window at the start of your project
The main Xcode window at the start of your project

This is very similar to what you saw when you created your first SwiftUI app, but there are some minor differences which you’ll learn about later on.

Adding a button

➤ In the Project navigator, find the item named Main.storyboard and click it once to select it:

The Project navigator lists the files in the project
The Project navigator lists the files in the project

Like a superhero changing his or her clothes in a phone booth, the main editing pane now transforms into the Interface Builder. This tool lets you drag-and-drop user interface components such as buttons to create the UI of your app.

➤ If it’s not already blue, click the Hide or Show the Inspectors button in Xcode’s toolbar.

Click this button to show the Utilities pane
Click this button to show the Utilities pane

These toolbar buttons in the top-right corner change the appearance of Xcode. This one in particular opens a new pane on the right side of the Xcode window.

Your Xcode should now look something like this:

Editing Main.storyboard in Interface Builder
Editing Main.storyboard in Interface Builder

This is the storyboard for your app. The storyboard contains the designs for all of your app’s screens and shows the navigation flow in your app from one screen to another.

Currently, the storyboard contains just a single screen or scene, represented by a rectangle in the middle of the Interface Builder canvas.

Note: If you don’t see the rectangle labeled “View Controller” but only an empty canvas, then use your mouse or trackpad to scroll the storyboard around a bit. Trust me, it’s in there somewhere! Also make sure your Xcode window is large enough. Interface Builder takes up a lot of space…

The scene currently is probably set to the size of an iPhone XR. To keep things simple, you will first design the app for the iPhone 8, which has a smaller screen. Later, you’ll also make the app fit on the larger iPhone models.

➤ At the bottom of the Interface Builder window, click View as: iPhone XR to open up the following panel:

Choosing the device type
Choosing the device type

Select the iPhone 8, thus resizing the preview UI you see in Interface Builder to be set to that of an iPhone 8. You’ll notice that the scene’s rectangle now becomes a bit smaller.

Do note that depending on the size of your Xcode window, the above panel might also look something like this:

Choosing the device type - compact view
Choosing the device type - compact view

If you get this screen, just select the iPhone 8 from the list of choices you get when you click on Device.

➤ In the Xcode toolbar, make sure it says Bullseye > iPhone 8 (next to the Stop button). If it doesn’t, then click it and pick iPhone 8 from the list.

Now, when you run the app, it will run on the iPhone 8 Simulator (try it out!).

Back to the storyboard.

➤ The first button on the top right toolbar shows the Library panel when you click it:

The Object Library
The Object Library

Scroll through the items in the Object Library list until you see Button. Alternatively, you can type the word “button” in to the search/filter box at the top.

➤ Click on Button and drag it onto the working area, on top of the scene’s rectangle.

Dragging the button on top of the scene
Dragging the button on top of the scene

That’s how easy it is to add most new UI items — just drag and drop. You’ll do a lot of this, so take some time to get familiar with the process.

Drag and drop a few other controls, such as labels, sliders, and switches, just to get the hang of it. Once you are done, delete everything except for the first button you added.

This should give you some idea of the UI controls that are available in iOS. Notice that the Interface Builder helps you to lay out your controls by snapping them to the edges of the view and to other objects. It’s a very handy tool!

➤ Double-click the button to edit its title. Call it Hit Me!

The button with the new title
The button with the new title

It’s possible that your button might have a border around it:

The button with a bounds rectangle
The button with a bounds rectangle

This border is not part of the button, it’s just there to show you how large the button is. You can turn these borders on or off using the Editor ▸ Canvas ▸ Show Bounds Rectangles menu option.

When you’re done playing with Interface Builder, press the Run button from Xcode’s toolbar. The app should now appear in the simulator, complete with your “Hit Me!” button. However, when you tap the button, it doesn’t do anything yet. For that, you’ll have to write some Swift code!

Using the source code editor

A button that doesn’t do anything when tapped is of no use to anyone. So let’s make it show an alert pop-up. In the finished game, the alert will display the player’s score; for now, you will limit yourself to a simple text message (the traditional “Hello, World!”).

➤ In the Project navigator, click on ViewController.swift.

The Interface Builder will disappear and the editor area now contains a bunch of brightly colored text. This is the Swift source code for your app.

➤ Add the following lines directly above the very last } bracket in the file:

@IBAction func showAlert() {
}

The source code for ViewController.swift should now look like this:

import UIKit

class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
  }
  
  @IBAction func showAlert() {
  }
}

View controllers

You’ve edited the Main.storyboard file to build the user interface of the app. It’s only a button on a white background, but a user interface nonetheless. You also added source code to ViewController.swift.

These two files — the storyboard and the Swift file — together form the design and implementation of a view controller. A lot of the work in building iOS apps is making view controllers. The job of a view controller, generally, is to manage a single screen in your app.

Take a simple cookbook app, for example. When you launch the cookbook app, its main screen lists the available recipes.

Tapping a recipe opens a new screen that shows the recipe in detail with an appetizing photo and cooking instructions.

Each of these screens is managed by a view controller.

The view controllers in a simple cookbook app
The view controllers in a simple cookbook app

What these two screens do is very different. One is a list of several items; the other presents a detail view of a single item.

That’s why you need two view controllers: One that knows how to deal with lists and another that can handle images and cooking instructions. One of the design principles of iOS is that each screen in your app gets its own view controller.

Currently, Bullseye has only one screen (the white one with the button) and thus only needs one view controller. That view controller is simply named “ViewController,” and the storyboard and Swift file work together to implement it.

If you are curious, you can check the connection between the screen and the code for it by switching to the Identity inspector on the right sidebar of Xcode in the storyboard view. The Class value shows the current class associated with the storyboard scene.

Simply put, the Main.storyboard file contains the design of the view controller’s user interface, while ViewController.swift contains its functionality — the logic that makes the user interface work, written in the Swift language.

Because you used the Single View Application template, Xcode automatically created the view controller for you. Later, you will add a second screen to the game and you will create your own view controller for that.

Making connections

The two lines of source code you just added to ViewController.swift lets Interface Builder know that the controller has a “showAlert” action, which presumably will show an alert pop-up. You will now connect the button on the storyboard to that action in your source code.

➤ Click Main.storyboard to go back into Interface Builder.

In Interface Builder, there should be a second pane on the left, next to the navigator area, called the Document Outline, that lists all the items in your storyboard. If you do not see that pane, click the small toggle button in the bottom-left corner of the Interface Builder canvas to reveal it.

The button that shows the Document Outline pane
The button that shows the Document Outline pane

➤ Click the Hit Me button once to select it.

With the Hit Me button selected, hold down the Control key, click on the button and drag up to the View Controller item in the Document Outline. You should see a blue line going from the button up to View Controller.

Please note that, instead of holding down Control, you can also right-click and drag, but don’t let go of the mouse button before you start dragging.

Ctrl-drag from the button to View Controller
Ctrl-drag from the button to View Controller

Once you’re on View Controller, let go of the mouse button and a small menu will appear. It contains several sections: “Action Segue,” “Sent Events,” and “Non-Adaptive Action Segue,” with one or more options below each. You’re interested in the showAlert option under Sent Events.

The Sent Events section shows all possible actions in your source code that can be hooked up to your storyboad — showAlert is the name of the action that you added earlier in the source code of ViewController.swift.

The pop-up menu with the showAlert action
The pop-up menu with the showAlert action

➤ Click on showAlert to select it. This instructs Interface Builder to make a connection between the button and the line @IBAction func showAlert().

From now on, whenever the button is tapped the showAlert action will be performed. That is how you make buttons and other controls do things: You define an action in the view controller’s Swift file and then you make the connection in Interface Builder. You can see that the connection was made by going to the Connections inspector in the Utilities pane on the right side of the Xcode window. You should have the button selected when you do this.

➤ Click the small arrow-shaped button at the top of the pane to switch to the Connections inspector:

The inspector shows the connections from the button to any other objects
The inspector shows the connections from the button to any other objects

In the Sent Events section, the “Touch Up Inside” event is now connected to the showAlert action. You should also see the connection in the Swift file.

➤ Select ViewController.swift to edit it.

Notice how, to the left of the line with @IBAction func showAlert(), there is a solid circle? Click on that circle to reveal what this action is connected to.

A solid circle means the action is connected to something
A solid circle means the action is connected to something

Acting on the button

You now have a screen with a button. The button is hooked up to an action named showAlert that will be performed when the user taps the button. Currently, however, the action is empty and nothing will happen (try it out by running the app again, if you like). You need to give the app more instructions.

➤ In ViewController.swift, modify showAlert to look like the following:

@IBAction func showAlert() {
  let alert = UIAlertController(title: "Hello, World",
                                message: "This is my first app!",
                                preferredStyle: .alert)

  let action = UIAlertAction(title: "Awesome", style: .default,
                             handler: nil)

  alert.addAction(action)

  present(alert, animated: true, completion: nil)
}

The code in showAlert creates an alert with a title “Hello, World,” a message that states, “This is my first app!” and a single button labeled “Awesome.”.

➤ Click the Run button from Xcode’s toolbar. If you didn’t make any typos, your app should launch in iOS Simulator and you should see the alert box when you tap the button.

The alert pop-up in action
The alert pop-up in action

Congratulations, you’ve just written your first UIKit app!

You can strike off the first two items from the to-do list already: Putting a button on the screen and showing an alert when the user taps the button.

The anatomy of an app

It might be good at this point to get some sense of what goes on behind the scenes of an app.

An app is essentially made up of objects that can send messages to each other. Many of the objects in your app are provided by iOS; for example, the button is a UIButton object and the alert pop-up is a UIAlertController object. Some objects you will have to program yourself, such as the view controller.

These objects communicate by passing messages to each other. For example, when the user taps the Hit Me button in the app, that UIButton object sends a message to your view controller. In turn, the view controller may message more objects.

On iOS, apps are event-driven, which means that the objects listen for certain events to occur and then process them.

As strange as it may sound, an app spends most of its time doing… absolutely nothing. It just sits there waiting for something to happen. When the user taps the screen, the app springs to action for a few milliseconds, and then it goes back to sleep again until the next event arrives.

Your part in this scheme is that you write the source code for the actions that will be performed when your objects receive the messages for such events.

In the app, the button’s Touch Up Inside event is connected to the view controller’s showAlert action. So when the button recognizes it has been tapped, it sends the showAlert message to your view controller.

Inside showAlert, the view controller sends another message, addAction, to the UIAlertController object. And to show the alert, the view controller sends the present message.

Your whole app will be made up of objects that communicate in this fashion.

Maybe you have used PHP or Ruby scripts on your web site. This event-based model is different from how a PHP script works. The PHP script will run from top-to-bottom, executing the statements one-by-one until it reaches the end and then it exits.

Apps, on the other hand, don’t exit until the user terminates them (or they crash!). They spend most of their time waiting for input events, then handle those events and go back to sleep.

Input from the user, mostly in the form of touches and taps, is the most important source of events for your app, but there are other types of events as well. For example, the operating system will notify your app when the user receives an incoming phone call, when it has to redraw the screen, when a timer has counted down, etc.

The general flow of events in an app
The general flow of events in an app

Everything your app does is triggered by some event.

You can find the project files for the app up to this point under 15-The One-Button App in the Source Code folder.

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.
© 2026 Kodeco Inc.