Home iOS & Swift Books iOS Apprentice

2
UIKit & the One-Button App Written by Eli Ganim

You are about to take the first step on your journey to iOS developer mastery. And you will take that first step by creating the Bull’s Eye game.

In this section you’ll build the Bullseye game.

This chapter covers the following:

  • The Bullseye game: An introduction to the first app you’ll make.
  • 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

This is what the Bullseye game will look like when you’re finished:

The finished Bullseye game
The finished Bullseye game

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.

This game probably won’t make you an instant millionaire on the App Store, but even future millionaires have to start somewhere!

Making a programming to-do list

Exercise: Now that you’ve seen what the game will look like and what the gameplay rules are, make a list of all the things that you think you’ll need to do in order to build this game. It’s OK if you draw a blank, but give it a shot anyway.

Here’s an example:

The app needs to put the “Hit Me!” button on the screen and show an alert pop-up when the user presses it.

Try to think of other things the app needs to do — it doesn’t matter if you don’t actually know how to accomplish these tasks. The first step is to figure out what you need to do; how to do these things is not important yet.

Once you know what you want, you can also figure out how to do it, even if you have to ask someone or look it up. But the “what” comes first. You’d be surprised at how many people start writing code without a clear idea of what they’re actually trying to achieve. No wonder they get stuck! Whenever you start working on a new app, it’s a good idea to make a list of all the different pieces of functionality you think the app will need. This will become your programming to-do list. Having a list that breaks up a design into several smaller steps is a great way to deal with the complexity of a project.

You may have a cool idea for an app, but when you sit down to write the program it can seem overwhelming. There is so much to do… and where to begin? By cutting up the workload into small steps you make the project less daunting – you can always find a step that is simple and small enough to make a good starting point and take it from there.

Don’t worry if you find this exercise challenging. You’re new to all of this! As you gain more programming experience, you’ll find it easier to identify the different parts that make up a design and become better at spliting it into manageable pieces.

Here’s an example of a to-do list based on the description of Bullseye:

  • 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)

Time to start coding! I’m assuming you have downloaded and installed the latest version of Xcode at this point.

In this book, you’ll work with Xcode 11.4 or greater. Newer versions of Xcode may also work, but anything older than version 11.4 probably would be a no-go.

Creating a new project

➤ Launch Xcode. If you have trouble locating the Xcode application, you can find it in the /Applications/Xcode folder or in your Launchpad. Because I use Xcode all of the time, I’ve placed it in my dock for easy access.

Xcode shows the “Welcome to Xcode” window when it starts:

Xcode start screen
Xcode start screen

➤ Choose Create a new Xcode project. The main Xcode window appears with an assistant that lets you choose a template:

Choosing the template for the new project
Choosing the template for the new project

Xcode has bundled templates for a variety of app styles. Xcode will make a pre-configured project for you based on the template you choose. The new project will already include some of the source files you need. These templates are handy because they can save you a lot of typing. They are ready-made starting points.

➤ Select Single View Application and press Next.

This opens a dialog where you can enter options for the new app.

Configuring the new project
Configuring the new project

➤ 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

  • User Interface: Storyboard

  • 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.

➤ Press Next. Now, Xcode will ask where to save your project.

➤ Choose a location for the project files; for example, the Desktop or your Documents folder.

Xcode will automatically make a new folder for the project using the Product Name that you entered in the previous step (in your case, Bullseye), so you don’t need to make a new folder yourself.

At the bottom of the File Save dialog, there is a checkbox that says, “Create Git repository on My Mac.” You can ignore this for now. You’ll learn about the Git version control system later on.

➤ Press Create to finish.

Xcode will now create a new project named Bullseye, based on the Single View Application template, in the folder you specified.

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

Running your project

➤ Press the Run button in the top-left corner.

Press Run to launch the app
Press Run to launch the app

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 11 Pro Max. 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 11 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 02-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.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2021 Razeware LLC