2.
The One-Button App
Written by Fahim Farook
There’s an old Chinese proverb that says, “A journey of a thousand miles begins with a single step.” You are about to take that first step on your journey to iOS developer mastery. And you will take that first step by creating the Bull’s Eye game.
This chapter covers the following:
- The Bull’s Eye 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 Bull’s Eye game
This is what the Bull’s Eye game will look like when you’re finished:
The objective of the game is to put the bull’s eye, 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 bull’s eye 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, also known as an alert, 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 by pressing the OK button, a new round begins with a new random target. The game repeats until the player presses the “Start Over” button (the curly arrow in the bottom-left corner), 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.
I’ll give you 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 I start working on a new app, I first make a list of all the different pieces of functionality I think the app will need. This becomes my 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.
It’s no big deal if this exercise gives you some difficulty. You’re new to all of this! As your understanding grows of how software and the development process works, it will become easier to identify the different parts that make up a design and to split it into manageable pieces.
This is what I came up with. I simply took the gameplay description and split it into very small chunks:
-
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. :]
I might have missed a thing or two, but this looks like a decent list to start with. Even for a game as basic as this, there are quite a few things you need to do. Making apps is fun, but it’s definitely a lot of work, too!
The one-button app
Let’s 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:
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 16.0 or better. Newer versions of Xcode may also work, but anything older than version 16.0 might not work correctly with the code in this book.
Because Swift is a new-ish language, it tends to change between versions of Xcode. If your Xcode is too old — or too new! — then not all of the code in this book may work properly. For this same reason, you’re advised not to use beta versions of Xcode, only the official one from the Mac App Store.
Creating a new project
➤ Launch Xcode. If you have trouble locating the Xcode application, you can find it in the /Applications 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:
➤ Choose Create New Project…. The main Xcode window appears with an assistant that lets you choose a template:
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 iOS from the top list of platforms, and then App from the list of templates under the Application section and press Next.
This opens a dialog where you can enter options for the new app.
➤ Fill out these options as follows:
-
Product Name: BullsEye. If you want to use proper English, you can name the project Bull’s Eye instead of BullsEye, but it’s best to avoid spaces and other special characters in project names.
-
Team: If you’re already a member of the Apple Developer Program, this will show your team name. For now, it’s best to leave this setting alone; we’ll get back to this later on.
-
Organization Identifier: Mine says “com.kodeco”. That is the identifier I use for my apps. As is customary, it is my domain name written in reverse. You should use your own identifier here. Pick something that is unique to you, either the domain name of your website (but backwards) or simply your own name. You can always change this later.
-
Interface: Set this to Storyboard. The other option for this dropdown is SwiftUI. That lets you develop applications using SwiftUI, which we won’t be covering in this book since our focus is on developing using UIKit.
-
Language: Swift. This is basically the programming language you’ll be using. The other option is Objective-C, but our focus will be on Swift.
Make sure the last two options — Testing System and Storage — are set to None. 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 template you selected, in the folder you specified.
When it is done, the screen should look something like this:
There may be small differences with what you’re seeing on your own computer if you’re using a version of Xcode newer than my version. Rest assured, any differences will only be superficial.
Note: If you don’t see a file named ViewController.swift in the list on the left but instead have ViewController.h and ViewController.m, then you picked the wrong language (Objective-C) when you created the project. Start over and be sure to choose Swift as the programming language.
Running your project
➤ Press the Run button in the top-left corner.
Note: If this is the first time you’re using Xcode, it may ask you to enable developer mode. Click Enable and enter your password to allow Xcode to make these changes.
Also, make sure that you do not have your iPhone or iPad plugged in at this point to your computer — for example, for charging. If you do, it might switch to the actual device instead of the simulator for running the app and, since you are not yet set up for running on a device, this could result in errors that might leave you scratching your head.
Xcode will labor for a bit and then launch your brand new app in an iOS Simulator. The app may not look like much yet — and there is not anything you can do with it either — but this is an important first milestone in your journey!
If Xcode says “Build Failed” or “Xcode cannot run using the selected device” when you press the Run button, then make sure the picker at the top of the window says BullsEye > iPod touch (or any other device model) and not Generic iOS Device:
If your iPhone is currently connected to your Mac via USB cable, Xcode may have attempted to run the app on your iPhone, and that may not work without some additional setting up. I’ll show you how to get the app to run on your iPhone so that you can show it off to your friends soon, but for now just stick with the iOS Simulator.
➤ To the left of the Run button is the Stop button (the square thingy). Press that to exit the app.
On your phone (or even the simulator), you’d use the Home button to exit an app (on the simulator, you could also use the Device ▸ Home item from the menu bar or use the handy ⇧+⌘+H shortcut), but that won’t actually terminate the app. The app will disappear from the simulator’s screen, but it stays suspended in the simulator’s memory, just as it would on a real iPhone.
Until you press Stop, Xcode’s Activity viewer at the top says, “Running BullsEye on iPod touch”:
It’s not really necessary to stop the app, as you can go back to Xcode and make changes to the source code while the app is still running. However, these changes will not become active until you press Run again. That will terminate any running version of the app, build a new version, and launch it in the simulator.
What happens when you press Run?
Xcode will first compile your source code — that is, translate it – from Swift into machine code that the iPhone (or iOS Simulator) can understand. Even though the programming language for writing iOS apps is Swift or Objective-C, the iPhone itself doesn’t speak those languages. A translation step is necessary.
The compiler is the part of Xcode that converts your Swift source code into executable binary code. It also gathers all the different components that make up the app — source files, images, storyboard files and so on — and puts them into the “application bundle.”
This entire process is also known as building the app. If there are any errors (such as spelling mistakes in your code), the build will fail. If everything goes according to plan, Xcode copies the application bundle to the simulator or the iPhone and launches the app. All that from a single press of the Run button.
Adding a button
I’m sure you’re as unimpressed as I am with an app that just displays a dull white screen! So let’s make it a bit more interesting by adding a button to it.
The left pane of the Xcode window is named the Navigator area. The row of icons along the top lets you select a specific navigator. The default navigator is the Project navigator, which shows the files in your project.
The organization of these files corresponds to the project folder on your hard disk, but that isn’t necessarily always so. You can move files around and put them into new groups and organize away to your heart’s content. We’ll talk more about the different files in your project later.
➤ In the Project navigator, find the item named Main.storyboard and click it once to select it:
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. (OK, maybe a bad analogy, but Interface Builder is a super tool, in my opinion.)
➤ If there is no sidebar on the right side of the Xcode window, click the Hide or show the inspectors button in the right-hand side of Xcode’s toolbar.
This toolbar button opens the Inspectors pane on the right side of the Xcode window. Your Xcode window should now look something like this:
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 the big white device frame in the middle of the Interface Builder canvas.
The grey frame enclosing the smaller white frame on the top right, in case you’re wondering, is the minimap. It shows a preview of the whole canvas so that you can navigate around quickly — you’ll see how it works as you add more screens to your app.
Given that there are many devices of differing screen sizes, the scene could be set to any of the available iPhone sizes. To keep things simple, you will first design the app for the iPhone SE, which has one of the smallest available screen sizes. Later, you’ll also make the app fit on the larger iPhone models.
➤ At the bottom of the Interface Builder window, click the tiny screen icon to the left of the text saying iPhone 16 — depending on your Xcode, it might say something other than “iPhone 16” — to open up the following pop-up:
Select iPhone SE (3rd Generation) from the list of devices. This will change (and resize) the preview UI you see in Interface Builder to that of an iPhone SE.
➤ In the Xcode toolbar, make sure it says BullsEye > iPhone SE (3rd Generation) in the central area, like this:
➤ If it doesn’t, then click the Choose Device dropdown and pick iPhone SE from the list:
Now, when you run the app, it will run on the iPhone SE (3rd Generation) Simulator (try it out!).
Back to the storyboard:
➤ The plus (+) button on the top toolbar shows the Library panel when you click it:
Select Button from the Object Library list (or scroll till you see it). 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.
That’s how easy it is to add most new UI (user interface) 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!
It’s possible that your button might have a border around it:
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 ▸ 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.
A new tab will be added to the Xcode interface alongside the Interface Builder tab and the editor area in the new tab will contain a bunch of colored text. This is the Swift source code for the main view of your app:
Note: If your Xcode editor window does not show the line numbers as in the screenshot above, and you’d actually like to see the line numbers, from the menu bar choose Xcode ▸ Settings… ▸ Text Editing and go to the Display tab. There, you should see a Line numbers checkbox under Show — check it.
➤ 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() {
}
}
Yes, that code leaves out the bunch of grey text above the code with a copyright notice. And that’s totally fine since that text is just a comment block, or notes for developers, and not a necessary part of the code.
Before I can tell you what the code means, I have to introduce the concept of a view controller.
Xcode will autosave
You don’t have to save your files after you make changes to them because Xcode will automatically save any modified files when you press the Run button.
Nevertheless, Xcode isn’t the most stable piece of software out there and, occasionally, it may crash on you before it has had a chance to save your changes.
Therefore, do remember to press ⌘+S on a regular basis to save any changes that you’ve made.
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.
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, Bull’s Eye 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 App 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 the Main.storyboard tab 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 on the very left of the Interface Builder toolbar to reveal it.
➤ 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.
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.
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 storyboard — showAlert is the name of the action that you added earlier in the source code of ViewController.swift.
➤ 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 last icon at the top of the pane to switch to the Connections inspector:
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 the ViewController.swift tab 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.
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 new lines of code implement the actual alert display functionality. The commands between the { }
brackets of the action tell the iPhone what to do, and they are performed from top to bottom. The code in showAlert
creates an alert — an iOS component which shows a message — with a title “Hello, World,” a message that states, “This is my first app!” and a single button labeled “Awesome.”
If you’re not sure about the distinction between the title and the message: Both show text, but the title is slightly bigger and in a bold typeface.
➤ Click the Run button on Xcode’s toolbar. If you didn’t make any typos, your app should launch in the iOS Simulator and you should see the alert box when you tap the button.
Congratulations, you’ve just written your first iOS app! What you just did may have seemed like gibberish to you, but that shouldn’t matter. We’ll take it one small step at a time.
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.
Take a little break, let it all sink in and come back when you’re ready for more! You’re only just getting started…
Note: Just in case you get stuck, I have provided the complete Xcode projects, which are snapshots of the project as at the beginning and end of each chapter. That way, you can compare your version of the app to mine, or — if you really make a mess of things — continue from a version that is known to work.
You can find the project files for each chapter in the corresponding folder.
Problems?
If Xcode gives you a “Build Failed” error message after you press Run, then make sure you typed in everything correctly. Even the smallest mistake could potentially confuse Xcode. It can be quite overwhelming at first to make sense of the error messages that Xcode spits out.
A small typo at the top of a source file can produce several errors elsewhere in that file.
One common mistake is differences in capitalization. The Swift programming language is case-sensitive, which means it sees Alert
and alert
as two different names. Xcode complains about this with a “Cannot find <something> in scope” error.
When Xcode says things like “Expected <something>” then you probably forgot a curly bracket }
or parenthesis )
somewhere. Not matching up opening and closing brackets is a common error.
Tip: In Xcode, there are multiple ways to find matching brackets to see if they line up. If you move the editing cursor past a closing bracket, Xcode will highlight the corresponding opening bracket, or vice versa. You could also hold down the ⌘ key and move your mouse cursor over a line with a curly bracket and Xcode will highlight the full block from the opening curly bracket to the closing curly bracket (or vice versa) — nifty!
Tiny details are very important when you’re programming. Even one single misplaced character can prevent the Swift compiler from building your app.
Fortunately, such mistakes are easy to find.
When Xcode detects an error, it switches the pane on the left from the Project navigator, to the Issue navigator, which shows all the errors and warnings that Xcode has found. (You can go back to the project navigator using the small icons along the top of the left pane.) In the above screenshot, apparently, I forgot a comma.
Click on the error message in the Issue navigator and Xcode takes you to the line in the source code with the error. Sometimes, depending on the error, it even suggests a fix:
It could be a bit of a puzzle to figure out what exactly you did wrong when your build fails — fortunately, Xcode lends a helping hand.
Errors and warnings
Xcode makes a distinction between errors (red) and warnings (yellow). Errors are fatal. If you get one, you cannot run the app until the error is fixed. Warnings are informative. Xcode just says, “You probably didn’t mean to do this, but go ahead anyway.”
In the previous screenshot showing all the error locations via arrows, you’ll notice that there is a warning (a yellow triangle) in the Issue navigator. We’ll discuss this particular warning and how to fix it later on. Generally though, it is best to treat all warnings as if they were errors. Fix the warning before you continue and only run your app when there are zero errors and zero warnings. That doesn’t guarantee the app won’t have any bugs, but at least they won’t be silly ones!
UIKit
As the name implies, this book deals with programming iOS applications using UIKit. But what exactly is UIKIt?
iOS offers a lot of building blocks in the form of frameworks or “kits.” You’ve used two of these building blocks already to start creating the Bullseye app — buttons and alerts. UIKit also manages the view controllers and generally takes care of anything else that deals with your app’s user interface. (That is what UI stands for: User Interface.)
If you had to write all that stuff from scratch, you’d be busy for a long while. Instead, you can build your app on top of the system-provided frameworks and take advantage of all the work the Apple engineers have already put in.
Any object you see whose name starts with UI, such as UIButton
, comes from UIKit. When you’re writing iOS apps, UIKit is the framework you’ll spend most of your time with, but there are others as well.
Examples of other frameworks are Foundation, which provides many of the basic building blocks for building apps; Core Graphics for drawing basic shapes such as lines, gradients and images on the screen; AVFoundation for playing sound and video; and many others.
The complete set of frameworks for iOS is known collectively as Cocoa Touch.
The anatomy of an app
While you’re learning about the bits that help you build iOS apps, it might be good at this point to get some sense of what goes on behind the scenes of an app, too.
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.
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.