1.
Checking Your Tools
Written by Audrey Tam
You’re eager to dive in and create your first iOS app. If you’ve never used Xcode before, take some time to work through this chapter. You want to be sure your tools are working and learn how to use them efficiently.
Getting Started
To develop iOS apps, you need a Mac with Xcode installed. If you have an account on GitHub or similar, you can connect to that from Xcode.
macOS
To use the SwiftUI canvas, you need a Mac running Catalina (V10.15) or later. To install Xcode, your user account must have administrator status.
Xcode
To install Xcode, you need 23 GB free space on your Mac’s drive.
➤ Open the App Store app, then search for and GET Xcode. This is a large download — almost 8GB — so it takes a while. Fix yourself a snack while you wait or, to stay in the flow, browse Chapter 12, “Apple App Development Ecosystem”.
➤ When the installation finishes, OPEN it from the App Store page:
Note: You probably have your favorite way to open a Mac application, and it will work with Xcode, too. Double-click it in Applications. Or search for it in Spotlight. Or double-click a project’s .xcodeproj file.
The first time you open Xcode after App Store installation, you’ll see this window:
➤ iOS and macOS are built into the 23 GB. Click Install and enter your Mac login password in the window that appears. This doesn’t take long, so don’t go away.
➤ When this installation process finishes, you’ll see this Welcome window:
If you don’t want to see this window every time you open Xcode, uncheck “Show this window when Xcode launches”. You can manually open this window from the Xcode menu Window ▸ Welcome to Xcode or press Shift-Command-1. And, there is an Xcode menu item to perform each of the actions listed in this window.
Creating a New Xcode Project
You’ll create a new Xcode project just for this chapter. The next chapter provides a starter project that you’ll build on for the rest of Section 1.
➤ Click Create a new Xcode project. Or, if you want to do this without the Welcome window, press Shift-Command-N or select File ▸ New ▸ Project… from the menu.
A large set of choices appears:
➤ Select iOS ▸ App and click Next. Now, you get to name your project:
- For Product Name, type MyFirst.
- Skip Team as None for now.
- For Organization Identifier, type the reverse-DNS of your domain name. If you don’t have a domain name, just type something that follows this pattern, like org.audrey. The grayed-out Bundle Identifier changes to your-org-id.MyFirst. When you submit your app to the App Store, this bundle identifier uniquely identifies your app.
- For Interface, select SwiftUI.
- For Language, select Swift.
- Uncheck the checkboxes.
➤ Click Next. Here’s where you decide where to save your new project.
Note: When a project is open, you can find its location by selecting File ▸ Show in Finder from the Xcode menu. If you forget where you saved a project, try looking in the Xcode menu File ▸ Open Recent.
➤ If you’re saving this project to a location that is not currently under source control, click the Source Control checkbox to create a local Git repository. Later in this chapter, you’ll learn how to connect this to a remote repository.
➤ Click Create. Your new project appears, displaying ContentView.swift in the editor pane.
Looks like there’s a lot going on! Don’t worry, most iOS developers know enough about Xcode to do their job, but almost no one knows how to use all of it. Plus, Apple changes and adds to it every year. The best (and only) way to learn it is to jump in and start using it.
Ready, set, jump!
A Quick Tour of Xcode
You’ll spend most of your time working in a .swift file:
Note: If you don’t see the file extension
.swift
in the Project navigator, press Command-, to open Settings… then, in the General tab, set File Extensions to Show All:
The Xcode window has three main panes: Navigator, Editor and Inspectors. When the app is running, the Debug Area opens below the Editor. When you’re viewing a SwiftUI View file in the Editor, you can view the preview canvas side-by-side with the code.
The toolbar button just above the Navigator pane hides or shows it. The same is true for the Inspectors pane. The debug area has a hide/show button in its own toolbar. You can also hide any of these three panes by dragging its border to the edge of the Xcode window.
And all three have keyboard shortcuts:
- Hide/show Navigators: Command-0
- Hide/show Inspectors: Option-Command-0
- Hide/show Debug Area: Shift-Command-Y
Note: There’s a handy cheat sheet of Xcode keyboard shortcuts in the assets folder for this chapter. It’s not a complete list, but it covers the ones people use most.
Navigator
The Navigator has nine tabs. When the navigator pane is hidden, you can open it directly in one of its tabs by pressing Command-1 to Command-9 (from left to right):
-
Project: Add, delete or group files. Open a file in the editor.
-
Source Control: View Git repository working copies, branches, commits, tags, remotes and stashed changes.
-
Symbol: Hierarchical or flat view of the named objects and methods.
-
Find: Search tool.
-
Issue: Build-time and runtime errors and warnings.
-
Test: Create, manage and run unit and UI tests.
-
Debug: Information about CPU, memory, disk and network usage while your app is running.
-
Breakpoint: Add, delete, edit and manage breakpoints.
-
Report: View or export reports and logs generated when you build and run the project.
The Filter field at the bottom is different for each tab. For example, the Project Filter lets you show only the files you recently worked on. This is handy for projects with a lot of files in a deeply nested hierarchy.
Editor
When you’re working in a code file, the Editor shows the code and a Minimap. The minimap is useful for long code files with many properties and methods. You can hover the cursor over the minimap to locate a specific property, then click to go directly to it. You don’t need it for the apps in this book, so you may want to hide it via the Adjust Editor Options button in the upper right corner of the editor.
When you’re working in a SwiftUI file, Option-Command-Return shows or hides the preview canvas.
The editor has browser features like tab and go back/forward. Keyboard shortcuts for tabs are the same as for web browsers: Command-T to open a new tab, Shift-Command-[ or -] to move to the previous or next tab, Command-W to close the tab and Option-click a tab’s close button to close all the other tabs. The back/forward button shows a list of previous/next files, but the keyboard shortcuts are Control-Command-right or -left arrow.
Inspectors
The Inspectors pane has three, four or five tabs, depending on what’s selected in the Project navigator. When this pane is hidden, you can open it directly in one of its tabs by pressing Option-Command-1 to Option-Command-5:
- File: Name, Full Path, Target Membership.
- History: Source Control log.
- Quick Help: Short form of Developer Documentation if you select a symbol in the editor.
- Accessibility: Accessibility information if you select a symbol in the preview.
- Attributes: Properties of the symbol you select in the editor.
All five tabs appear when you select a file in the Project navigator. If you select a folder, you get only the first three tabs. If you select Assets.xcassets, you don’t get the accessibility tab.
This quick tour just brushes the surface of what you can do in Xcode. Next, you’ll use a few of its tools while you explore your new project.
Navigation Settings
In this book, you’ll use keyboard shortcuts to examine and structure your code. Unlike the fixed keyboard shortcuts for opening navigator tabs or inspectors, you can specify settings for which shortcut does what. To avoid confusion while working through this book, you’ll adjust your settings to match the instructions you’ll see.
➤ Press Command-, to open Settings. In the Navigation tab, set:
- Command-click on Code to Selects Code Structure
- Option-click on Code to Shows Quick Help
- Navigation Style to your choice of Open in Tabs or Open in Place.
ContentView.swift
The heart of your new project is in ContentView.swift, where your new project opened. This is where you’ll lay out the initial view of your app.
➤ If ContentView.swift isn’t in the editor, select it in the Project navigator.
The first several lines are comments that identify the file and you, the creator.
import
The first line of code is an import
statement:
import SwiftUI
This works just like most programming languages: It allows your code to access everything in the built-in SwiftUI module. See what happens if it’s missing.
➤ Click the import
statement line, then press Command-/.
Note: All code on our site uses 2-space indentation to save space. Xcode defaults to 4-space indentation. You can change this in Xcode Settings ▸ Text Editing ▸ Indentation.
You commented out the import
statement, so compiler errors appear, complaining about View
and PreviewProvider
.
➤ Press Command-Z to undo.
Below the import
statement are two struct
definitions. A structure is a named data type that encapsulates properties and methods.
struct ContentView
The name of the first structure matches the name of the file. Nothing bad happens if they’re different, but most developers follow and expect this convention.
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.padding()
}
}
Looking at ContentView: View
, you might think ContentView
inherits from View
, but Swift structures don’t have inheritance. View
is a protocol, and ContentView
conforms to this protocol.
The required component of View
is the computed property body
, which returns a View
. In this case, it returns a VStack
(vertical stack) that displays a globe image and the usual “Hello, world!” text.
Swift Tip: A computed property returns the computed value. If there’s only a single code statement, you don’t need to explicitly use the
return
keyword.
The VStack
view has a padding
modifier — an instance method of View
— that adds space around the stack. You can see it in this screenshot:
This also shows the Accessibility inspector for the Image
and Text
subviews in VStack
— label, value, identifier and traits.
Image(systemName: "globe")
and its modifiers display a globe symbol. You’ll learn about the Image
view in Chapter 3, “Prototyping the Main View”.
Text("Hello, world!")
displays the string “Hello, world!”.
➤ Click the Selectable button below the preview canvas, then click the Text
view in the canvas and select the Quick Help inspector.
If you don’t want to use screen real estate for this inspector, Option-click Text
in the code editor to see the same information in a pop-up window. Scroll down in either window to see the Open in Developer Documentation button, which opens a window with more information.
➤ Now, select the Attributes inspector. Click in the Add Modifier field and wait a short while until the modifiers menu appears:
Scrolling through this list goes on and on and on.
This inspector is useful when you want to add several modifiers to a View
. If you just need to add one modifier, Control-Option-click the view in the code editor to open the Attributes inspector pop-up window.
struct ContentView_Previews
Below ContentView
is a ContentView_Previews
structure.
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
The ContentView_Previews
structure is what appears in the canvas on the right of the code editor. See what happens if it’s missing.
➤ Select the five lines of ContentView_Previews
and press Command-/.
Without ContentView_Previews
, there’s nothing in the canvas.
➤ Press Command-Z to undo or, if the five lines are still selected, press Command-/ to uncomment them.
You’ll sometimes want to give more space to the code editor, so your code doesn’t have to wrap.
➤ Press Option-Command-Return to hide the canvas. Press the same keyboard shortcut to show the canvas.
For most apps, ContentView.swift is just the starting point. Often, ContentView
only defines the app’s organization, orchestrating several subviews. And usually, you’ll define these subviews in separate files.
Creating a New SwiftUI View File
Everything you see in a SwiftUI app is a View
. Apple encourages you to create as many subviews as you need in order to avoid redundancy and organize your code to keep it manageable. The compiler takes care of creating efficient machine code so your app’s performance won’t suffer.
➤ In the Project navigator, select ContentView.swift and press Command-N. Alternatively, right-click ContentView.swift then select New File… from the menu.
Xcode Tip: A new file appears in the Project navigator below the currently selected file. If that’s not where you want it, drag it to where you want it to appear in the Project navigator.
The new file window displays a lot of options! The one you want is iOS ▸ User Interface ▸ SwiftUI View. In Chapter 3, “Prototyping the Main View”, you’ll get to create a Swift File.
Naming a New SwiftUI View
➤ Select SwiftUI View then click Next. The next window lets you specify a file name. By default, the name of the new view will be the same as the file name. You’ll define the ByeView
in this file, so replace SwiftUIView with ByeView.
Swift Tip: Swift convention is to name types (like
struct
) with UpperCamelCase and properties and methods with lowerCamelCase.
This window also lets you specify where in the project to create your new file. The default location is usually correct — in this project, in this group (folder) and in this target.
➤ Click Create to finish creating your new file.
The template code for a SwiftUI view is simpler than the ContentView
of a new project.
import SwiftUI
struct ByeView: View {
var body: some View {
Text("Hello, World!")
}
}
struct ByeView_Previews: PreviewProvider {
static var previews: some View {
ByeView()
}
}
The view’s body contains only Text("Hello, World!")
— no Image
, so you don’t need a VStack
, and no padding
. Another subtle difference: The “Hello, World!” string is a token. It’s just a placeholder. Clicking anywhere in it highlights the token so you can type in a new value.
Using Your New SwiftUI View
➤ Click the “Hello, World!” token and change it so the line looks like this:
Text("Bye bye, World!")
➤ Next, in ContentView.swift, in the code editor, delete the Text
view, then type bye. Xcode suggests some auto-completions:
Notice you don’t have to type the correct capitalization of ByeView
.
Xcode Tip: Descriptive names for your types, properties and methods is good programming practice, and auto-completion is one way Xcode helps you do the right thing. You can also turn on spell-checking from the Xcode menu: Edit ▸ Format ▸ Spelling and Grammar ▸ Check Spelling While Typing.
➤ Select ByeView() from the list, so the line looks like this:
ByeView()
You’re calling the initializer of ByeView
to create an instance of the view.
➤ In the canvas, if the preview is paused, click the refresh button:
Your new ByeView
has replaced the original Text
view. You’ll create many new SwiftUI view files and Swift files to develop the apps in this book.
What Else is in Your Project?
The Project navigator lists several files and folders.
- MyFirstApp.swift: This file contains the code for your app’s entry point. This is what actually launches your app.
@main
struct MyFirstApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
The @main
attribute marks MyFirstApp
as the app’s entry point. You might be accustomed to writing a main()
method to actually launch an app. The App
protocol takes care of this. The App
protocol requires only a computed property named body
that returns a Scene
. And a Scene
is a container for the root view of a view hierarchy.
For an iOS app, the default setup is a WindowGroup
scene containing ContentView()
as its root view. A common customization is to set different root views, depending on whether the user has logged in.
In an iOS app, the view hierarchy fills the entire display. In a macOS or iPadOS app, WindowGroup
can manage multiple windows.
- Assets.xcassets: Store your app’s images and colors here. AppIcon is a special image set for all the different sizes and resolutions of your app’s icon. Using Xcode 14, you can supply a single 1024x1024-point app icon image that Xcode resizes to get all the icon sizes for iOS, iPadOS and watchOS. Simply select Single Size in the Attributes inspector:
- Preview Content: If your views need additional code and sample data or assets while you’re developing your app, store them here. They won’t be included in the final distribution build of your app.
In this list, the last item is a group. Groups in the Project navigator appear to be folders, but they don’t necessarily match up with folders in Finder.
Note: Don’t rename or delete any of these files or groups. Xcode stores their path names in the project’s build settings and will flag errors if it can’t find them.
You’ll learn how to use these files in the rest of this book.
Xcode Settings
Xcode has a huge number of settings you can adjust to be more productive.
Themes
You’ll be spending a lot of time working in the code editor, so you want it to look good and also help you distinguish the different components of your code. Xcode provides several pre-configured font and color themes for you to choose from or modify.
➤ Press Command-, to open Settings, then select the Themes tab:
Go ahead and explore these. You can customize them or create your own. I’ll wait here. ;]
Matching Delimiters
SwiftUI code uses a lot of nested closures. It’s really easy to mismatch your braces and parentheses. Xcode helps you find any mismatches and tries to prevent these errors from happening.
➤ In Settings, select Text Editing ▸ Editing:
Most of the Code Completion items are super helpful. Although you can copy and paste code from this book, you should try to type the code as much as possible to learn how these aids work.
Here’s a big hint that something’s wrong or you’re typing in the wrong place: You’re expecting Xcode to suggest completions while you type, but nothing (useful) appears. When this happens, it’s usually because you’re outside the closure you need to be in.
➤ Now select the Text Editing ▸ Display tab. Check Code folding ribbon and, if you like to see them, Line numbers:
So what’s a code folding ribbon? Between the line numbers and the code, you see darker gray vertical bars.
➤ Hover your cursor over one — anywhere between VStack {
and padding()
.
It highlights the start and end braces of that closure:
Other ways to see matching delimiters:
- Option-hover over {, (, [ or a closing delimiter: Xcode highlights the start and end delimiters.
- Double-click a delimiter: Xcode selects the delimiters and their contents.
➤ Now click the bar (ribbon) to collapse (fold) those lines of code:
This can be incredibly useful when you’re trying to find your way around some complex, deeply-nested code.
➤ Click the ribbon to unfold the code.
Adding Accounts
You can access some Xcode features by adding login information for your Apple ID and source control accounts.
➤ In Settings, select Accounts:
➤ Click the + button in the lower left corner and add your Apple ID. If you have a separate paid Apple Developer account, add that too.
To add capabilities like push notifications or Apple Pay to your app, you need to set Team to a Developer Program account. You’d do this in the Signing & Capabilities tab of the target.
- If you have an account at Bitbucket, GitHub or GitLab, add it here if you want to push your project’s local git repository to a remote repository.
Bitbucket Server, GitHub and GitLab accounts require a personal access token. If the button to open GitHub’s token-creation page doesn’t work, open this URL.
➤ To set up a remote repository, open the Xcode Source Control menu and select New Git Repositories…:
If you remembered to check Create Git repository on my Mac when you created your project, you can skip this step.
➤ Click Create:
➤ Now, open the Source Control navigator (Command-2), click the Repositories tab and expand the repository:
➤ Control-click Remotes and select New “MyFirst” Remote…
➤ Select your options, then click Create:
And here it is:
Running Your Project
So far, you’ve relied on Live Preview to see what your app looks like. In the next chapter, you’ll use Live Preview to interact with your app. But some features don’t work in Live Preview, so you need to build and run your app on a simulator. And some things will only work on an iOS device. Plus, it’s fun to have something on your iPhone that you built yourself!
The Xcode Toolbar
First, a quick tour of Xcode’s toolbar:
Xcode Tip: Press Option-Command-T to show or hide the toolbar. If this keyboard shortcut conflicts with another app, select the command from the Xcode View menu.
So far, you’ve only used the buttons at either end of the toolbar, to show or hide the navigator or inspector panes.
Working from left to right after the navigation pane button:
- Run button: Build and run (Command-R) the project.
- Stop button appears when project is running: Stop (Command-.) the running project.
- Source control button: Shows branches and lets you create a pull request.
- Scheme menu: This button’s label is the name of the app. Select, edit or manage schemes. Each product has a scheme. MyFirst has only one product, so it has only one scheme.
- Run destination menu: This menu defaults to iPhone 14 Pro. Select a connected device or a simulated device to run the project.
- Activity view: A wide gray field that shows the project name, status messages and warning or error indicators.
- Library button: This button’s label is a + sign. It opens the library of views, modifiers, code snippets, media, colors stored in Assets and system symbols. Option-click this button to keep the library open.
Now that you know where the controls are, it’s time to use some of them.
Choosing a Run Destination or Preview Device
Apple sells iPhones and iPads in different sizes, and some have a notch. How do you know if your app looks good on every screen size?
You don’t need a complete collection of iOS devices. Xcode has several Developer Tools, and one of them is Simulator. The run destination menu lets you choose from a list of simulated devices.
➤ If it’s not already set, click the run destination button and select iPhone 14 Pro.
➤ In ContentView
, if the preview is paused, refresh it:
The preview uses the run destination device by default. You can create more than one preview and set each to a different device with the previewDevice
modifier.
Note: When you install Xcode 14, there might be only a few iPhone simulators in the destination run menu — mine lists only the iPhone 14 sizes and the iPhone SE 3rd generation. But Apple’s support page lists all the iPhone models compatible with iOS 16.
➤ Check your destination run menu: Is iPhone 8 listed? If not, select Add Additional Simulators…, type in iPhone 8, then click Create.
➤ Then replace ContentView_Previews
with the following:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ContentView()
ContentView()
.previewDevice(PreviewDevice(rawValue: "iPhone 8"))
}
}
}
Group
is another SwiftUI container. It doesn’t do any layout. It’s just useful when you need to wrap code that’s more complicated than a single view.
If you haven’t used this simulator device before, Xcode starts it up, then displays it on a second page:
Note: Enter
xcrun simctl list devicetypes
in a Terminal window to see a full list of supported preview device names.
The preview usually looks the same as your app running on a simulated or real device, but not always. If you feel the preview doesn’t match what your code is laying out, try running it on a simulator.
Build & Run
➤ Click the run button or press Command-R.
The first time you run a project on a simulated device, it starts from an “off” state, so you’ll see a loading indicator. Until you quit the Simulator app, this particular simulated device is now “awake”, so you won’t get the startup delay even if you run a different project on it.
After the simulated device starts up, the app’s launch screen appears. For MyFirst, this is just a blank screen. You’ll learn how to set up your own launch screen in Chapter 16, “Adding Assets to Your App”.
And now, your app is running!
There’s not much happening in this app, but the debug toolbar appears below the editor window. For this screenshot, I showed the debug area, selected the Debug tab in the Project navigator pane, then selected the CPU item.
In the following chapters, you’ll create a much more interesting app.
Not Stopping
Here’s a trick that will make your Xcode life a little easier.
➤ Don’t click the stop button. Yes, it’s enabled. But trust me, you’ll like this. :]
➤ In ByeView.swift, replace “Bye bye” with “Hello again”:
Text("Hello again, World!")
➤ Click the run button or press Command-R.
Up pops this message:
➤ Don’t click Replace yet, although that will work: The currently running process will stop, and the new process will run. This dialog will appear every time you forget to stop the app. It’s just a moment, but it jars a little. Every time. And it’s easy to get rid of.
➤ Check Don’t ask again, then click Replace.
The app loads with your new change. But that’s not what I want to show you.
➤ Once more: Click the run button or press Command-R.
No annoying message, no “doh!” moment, ever again! You’re welcome. ;]
Key Points
- The Xcode window has Navigator, Editor and Inspectors panes, a Toolbar and a Debug Area, plus a huge number of Settings.
- You can specify navigation keyboard shortcuts in Settings, to match the instructions in this book.
- The template project defines an
App
that launches withContentView
, displaying a globe symbol and “Hello, world!”. - You can view Quick Help documentation in an inspector or with a keyboard shortcut. Or, you can open the Developer Documentation window.
- When you create a new SwiftUI view file, give it the same name as the
View
you’ll create in it. - Xcode’s auto-completion, delimiter-matching, code-folding and spell-checking help you avoid errors.
- You can choose one of Xcode’s font and color themes, modify one or create your own.
- You can run your app on a simulated device or create previews of specific devices.