This lesson gets you familiar with Xcode, the tool you use to write apps. You’ll become familiar with the structure of a project in Xcode and learn how to navigate between and use basic project components. Throughout the lesson, you’ll start making a simple user interface (UI) for the FoodTracker app and view it in Simulator. When you’re finished, your app will look something like this:
Learning Objectives
At the end of the lesson, you’ll be able to:
- Create a project in Xcode
- Identify the function of key files that are created with an Xcode project template
- Open and switch between files in a project
- Run an app in Simulator
- Add, move, and resize UI elements in a storyboard
- Edit the attributes of UI elements in a storyboard using the Attributes inspector
- View and rearrange UI elements using the outline view
- Preview a storyboard UI using the Preview assistant editor
- Lay out a UI that automatically adapts to the user’s device size using Auto Layout
Create a New Project
Xcode includes several built-in app templates for developing common types of iOS apps, such as games, apps with tab-based navigation, and table-view-based apps. Most of these templates have preconfigured interface and source code files. For this lesson, you’ll start with the most basic template: Single View Application.
To create a new project
- Open Xcode from the
/Applications
directory.The Xcode welcome window appears.If a project window appears instead of the welcome window, don’t worry—you probably created or opened a project in Xcode previously. Just use the menu item in the next step to create the project. - In the welcome window, click “Create a new Xcode project” (or choose File > New > Project).Xcode opens a new window and displays a dialog in which you choose a template.
- In the iOS section at the left of the dialog, select Application.
- In the main area of the dialog, click Single View Application and then click Next.
- In the dialog that appears, use the following values to name your app and choose additional options for your project:
- Product Name:
FoodTracker
Xcode uses the product name you entered to name your project and the app. - Organization Name: The name of your organization or your own name. You can leave this blank.
- Organization Identifier: Your organization identifier, if you have one. If you don’t, use
com.example
. - Bundle Identifier: This value is automatically generated based on your product name and organization identifier.
- Language: Swift
- Devices: UniversalA Universal app is one that runs on both iPhone and iPad.
- Use Core Data: Unselected.
- Include Unit Tests: Selected.
- Include UI Tests: Unselected.
- Click Next.
- In the dialog that appears, select a location to save your project and click Create.Xcode opens your new project in the workspace window.
In the workspace window, you may or may not see a warning triangle with a message that says “No code signing identities found.” This warning means you haven’t set up Xcode for iOS development yet, but don’t worry, you can complete these lessons without doing that.
Get Familiar with Xcode
Xcode includes everything you need to create an app. It not only organizes the files that go into creating an app, it provides editors for code and interface elements, allows you to build and run your app, and includes a powerful integrated debugger.
Take a few moments to familiarize yourself with the main sections of the Xcode workspace. You’ll use the areas identified in the window below throughout the lessons. Don’t be overwhelmed by all of the pieces; each area is described in more detail when you need to use it.
Run Simulator
Because you based your project on an Xcode template, the basic app environment is automatically set up for you. Even though you haven’t written any code, you can build and run the Single View Application template without any additional configuration.
To build and run your app, use the Simulator app that’s included in Xcode. Simulator gives you an idea of how your app would look and behave if it were running on a device.
Simulator can model a number of different types of hardware—iPad, iPhone with different screen sizes, and so on—so you can simulate your app on every device you’re developing for. In this lesson, use the iPhone 6 option.
To run your app in Simulator
- In the Scheme pop-up menu in the Xcode toolbar, choose iPhone 6.The Scheme pop-up menu lets you choose which Simulator or device you’d like to run your app on. Make sure you select the iPhone 6 Simulator, not an iOS Device.
- Click the Run button, located in the top-left corner of the Xcode toolbar.Alternatively, choose Product > Run (or press Command-R).If you’re running an app for the first time, Xcode asks whether you’d like to enable developer mode on your Mac. Developer mode allows Xcode access to certain debugging features without requiring you to enter your password each time. Decide whether you’d like to enable developer mode and follow the prompts.If you choose not to enable developer mode, you may be asked for your password later on. The lessons assume developer mode is enabled.
- Watch the Xcode toolbar as the build process completes.Xcode displays messages about the build process in the activity viewer, which is in the middle of the toolbar.
After Xcode finishes building your project, Simulator starts automatically. It may take a few moments to start up the first time.
Simulator opens in iPhone mode, just as you specified. On the simulated iPhone screen, Simulator launches your app. Before the app finishes launching, you’ll briefly see a launch screen with your app’s name, FoodTracker.
Then, you should see something like this:
Right now, the Single View Application template doesn’t do much—it just displays a white screen. Other templates have more complex behavior. It’s important to understand a template’s uses before you extend it to make your own app. Running your app in Simulator with no modifications is a good way to start developing that understanding.
Quit Simulator by choosing Simulator > Quit Simulator (or pressing Command-Q).
Review the Source Code
The Single View Application template comes with a few source code files that set up the app environment. First, take a look at the
AppDelegate.swift
file.
To look at the AppDelegate.swift source file
- Make sure the project navigator is open in the navigator area.The project navigator displays all the files in your project. If the project navigator isn’t open, click the leftmost button in the navigator selector bar. (Alternatively, choose View > Navigators > Show Project Navigator.)
- If necessary, open the FoodTracker folder in the project navigator by clicking the disclosure triangle next to it.
- Select
AppDelegate.swift
.Xcode opens the source file in the main editor area of the window.Alternatively, double-click theAppDelegate.swift
file to open it in a separate window.
The App Delegate Source File
The
AppDelegate.swift
source file has two primary functions:- It creates the entry point to your app and a run loop that delivers input events to your app. This work is done by the
UIApplicationMain
attribute (@UIApplicationMain
), which appears toward the top of the file.UIApplicationMain
creates an application object that’s responsible for managing the life cycle of the app and an app delegate object, which is described below. - It defines the
AppDelegate
class, the blueprint for the app delegate object. The app delegate creates the window where your app’s content is drawn and provides a place to respond to state transitions within the app. TheAppDelegate
class is where you write your custom app-level code.
The
AppDelegate
class contains a single property: window
. With this property the app delegate keeps track of the window in which all of your app content is drawn. The window property is an optional, which means it may have no value (be nil) at some point.var window: UIWindow?
The
AppDelegate
class also contains template implementations of important methods. These predefined methods allow the application object to talk to the app delegate.func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
func applicationWillResignActive(application: UIApplication)
func applicationDidEnterBackground(application: UIApplication)
func applicationWillEnterForeground(application: UIApplication)
func applicationDidBecomeActive(application: UIApplication)
func applicationWillTerminate(application: UIApplication)
During an app state transition—for example, app launch, transitioning to the background, and app termination—the application object calls the corresponding method in the app delegate, giving it an opportunity to respond appropriately. You don’t need to do anything special to make sure these methods get called at the correct time—the application object handles that part of the job for you.
Each of these automatically implemented methods has a default behavior. If you leave the template implementation empty or delete it from your
AppDelegate
class, you get the default behavior whenever that method is called. Use these method templates to add custom code that will execute when the methods are called. In this lesson, you won’t be using any custom app delegate code, so you don’t have to make any changes to the AppDelegate.swift
file.The View Controller Source File
The Single View Application template has another source code file:
ViewController.swift
. SelectViewController.swift
in the project navigator to view it.
This file defines a custom subclass of
UIViewController
named ViewController
. Right now, this class simply inherits all the behavior defined by UIViewController
. To override or extend that behavior, you override the methods defined on UIViewController
(as you see done in the ViewController.swift
file with theviewDidLoad()
and didReceiveMemoryWarning()
methods), or implement your own custom methods.
Although the template comes with the
didReceiveMemoryWarning()
method, you won’t need to implement it in these lessons, so go ahead and delete it.
At this point, your
ViewController.swift
code should look something like this:import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
You’ll start writing code in this source code file later in this lesson.
Open Your Storyboard
You’re ready to start working on a storyboard for your app. A storyboard is a visual representation of the app’s user interface, showing screens of content and the transitions between them. You use storyboards to lay out the flow—or story—that drives your app. You see exactly what you're building while you’re building it, get immediate feedback about what’s working and what’s not, and make instantly visible changes to your UI.
To open your storyboard
- In the project navigator, select
Main.storyboard
.Xcode opens the storyboard in Interface Builder—its visual interface editor—in the editor area. The background of the storyboard is the canvas. You use the canvas to add and arrange UI elements.
Your storyboard should look similar to this:
At this point, the storyboard in your app contains one scene, which represents a screen of content in your app. The arrow that points to the left side of the scene on the canvas is the storyboard entry point, which means that this scene is loaded first when the app starts. Right now, the scene that you see on the canvas contains a single view that’s managed by a view controller. You’ll learn more about the roles of views and view controllers soon.
When you ran your app in the iPhone 6 Simulator app, the view in this scene is what you saw on the device screen. But when you look at the scene on the canvas, you’ll notice that it doesn’t have the exact dimensions of the iPhone 6 screen. This is because the scene on the canvas is a generalized representation of your interface that can apply to any device in any orientation. You use this representation to create an adaptive interface, which is an interface that automatically adjusts so that it looks good in the context of the current device and orientation.
Build the Basic UI
It’s time to build a basic interface. You’ll start by working on a UI for the scene that lets you add a new meal to your meal tracking app, FoodTracker.
Xcode provides a library of objects that you can add to a storyboard file. Some of these are elements that appear in the UI, such as buttons and text fields. Others, such as view controllers and gesture recognizers, define the behavior of your app but don’t appear onscreen.
The elements that appear in the UI are known as views. Views display content to the user. They are the building blocks for constructing your UI and presenting your content in a clear, elegant, and useful way. Views have a variety of useful built-in behavior, including displaying themselves onscreen and reacting to user input.
All view objects in iOS are of type
UIView
or one of its subclasses. Many UIView
subclasses are highly specialized in appearance and behavior. Start by adding a text field (UITextField
), one such subclass ofUIView
, to your scene. A text field lets a user type in a single line of text, which you’ll use as the name of a meal.
To add a text field to your scene
- Open the Object library.The Object library appears at the bottom of the utility area on the right side of Xcode. If you don’t see the Object library, click its button, which is the third button from the left in the library selector bar. (Alternatively, choose View > Utilities > Show Object Library.)A list appears showing each object’s name, description, and visual representation.
- In the Object library, type
text field
in the filter field to find the Text Field object quickly. - Drag a Text Field object from the Object library to your scene.If necessary, zoom in by choosing Editor > Canvas > Zoom.
- Drag the text field so that it’s positioned in the top half of the scene and aligned with the left margin in the scene.Stop dragging the text field when you see something like this:The blue layout guides help you place the text field. Layout guides are visible only when you drag or resize objects next to them; they disappear when you let go of the text field.
- If necessary, click the text field to reveal the resize handles.You resize a UI element by dragging its resize handles, which are small white squares that appear on the element’s borders. You reveal an element’s resize handles by selecting it. In this case, the text field should already be selected because you just stopped dragging it. If your text field looks like the one below, you’re ready to resize it; if it doesn’t, select it on the canvas.
- Resize the left and right edges of the text field until you see three vertical layout guides: the left margin alignment, the horizontal center alignment, and the right margin alignment.
Although you have the text field in your scene, there’s no instruction to the user about what to enter in the field. Use the text field’s placeholder text to prompt the user to enter the name of a new meal.
To configure the text field’s placeholder text
- With the text field selected, open the Attributes inspector in the utility area.The Attributes inspector appears when you click the fourth button from the left in the inspector selector bar. It lets you edit the properties of an object in your storyboard.
- In the Attributes inspector, find the field labeled Placeholder and type
Enter meal name
. - Press Return to display the new placeholder text in the text field.
Your scene should look similar to this:
While you’re editing the text field’s attributes, you can also edit the attributes of the system keyboard that’s displayed when a user selects the text field.
To configure the text field’s keyboard
- Make sure the text field is still selected.
- In the Attributes inspector, find the field labeled Return Key and select Done.This change will make the default Return key on the keyboard more pronounced to the user by changing it into a Done key.
- In the Attributes inspector, select the Auto-enable Return Key checkbox.This change makes it impossible for the user to tap the Done key before typing text into the text field, ensuring that users can never enter an empty string as a meal name.
Next, add a label (
UILabel
) at the top of the scene. A label isn’t interactive; it just displays static text in the UI. To help you understand how to define interaction between elements in the UI, you’ll configure this label to display the text the user enters into the text field. It’ll be a good way to test that the text field is taking the user input and processing it appropriately.
To add a label to your scene
- In the Object library, type
label
in the filter field to find the Label object quickly. - Drag a Label object from the Object library to your scene.
- Drag the label so that it’s right above the text field and aligned with the left margin in the scene.Stop dragging the label when you see something like this:
- Double-click the label and type
Meal Name
. - Press Return to display the new text in the label.
Your scene should look something like this:
Now, add a button (
UIButton
) to the UI. A button is interactive, so users can tap it to trigger an action that you define. Later, you’ll create an action to reset the label text to a default value.
To add a button to your scene
- In the Object library, type
button
in the filter field to find the Button object quickly. - Drag a Button object from the Object library to your scene.
- Drag the button so that it’s right below the text field and aligned with the left margin in the scene.Stop dragging the button when you see something like this:
- Double-click the button and type
Set Default Label Text
. - Press Return to display the new text in the button.
At this point, your scene should look something like this:
It’s good to understand how the elements you’ve added are actually arranged in the scene. Look at the outline view to see which UI elements have been added to your scene.
To view the outline view
- In your storyboard, find the outline view toggle.
- If the outline view is collapsed, click the toggle to expand the outline view.You can use the outline view toggle to collapse and expand the outline view as needed.
The outline view—which appears on the left side of the canvas—lets you see a hierarchical representation of the objects in your storyboard. You should be able to see the text field, label, and button you just added listed in the hierarchy. But why are the UI elements you added nested under View, that is, inside another view?
Views not only display themselves onscreen and react to user input, they can serve as containers for other views. Views are arranged in a hierarchical structure called the view hierarchy. The view hierarchy defines the layout of views relative to other views. Within that hierarchy, views enclosed within a view are called subviews, and the parent view that encloses a view is called its superview. A view can have multiple subviews and only one superview.
In general, each scene has its own view hierarchy. At the top of each view hierarchy is a content view. In the current scene, the content view is View, the top level view inside View Controller. The text field, label, and button are subviews of the content view. All other views that you place in this scene will be subviews of this content view (although they themselves can have nested subviews).
Preview Your Interface
Preview your app periodically to check that everything is looking the way you expect. You can preview your app interface using the assistant editor, which displays a secondary editor side-by-side with your main one.
To preview your interface
- Click the Assistant button in the Xcode toolbar near the top right corner of Xcode to open the assistant editor.
- If you want more space to work, collapse the project navigator and utility area by clicking the Navigator and Utilities buttons in the Xcode toolbar.You can also collapse the outline view.
- In the editor selector bar, which appears at the top of the assistant editor, switch the assistant editor from Automatic to Preview > Main.storyboard (Preview).
As you see in the assistant editor, the text field doesn’t look quite right. It extends past the edge of the screen. The interface you specified in your storyboard looks correct, so why is this happening in the iPhone preview?
As you learned earlier, you’re actually building an adaptive interface that scales for different sizes of iPhone and iPad. The scene you see by default in your storyboard shows a generalized version of your interface. Here, you’ll need to specify how the interface should adjust for different screen sizes and available area on the screen. For example, when the interface shrinks down to an iPhone size, the text field should shrink. When the interface grows to an iPad size, the text field should grow. You can specify these kinds of interface rules easily using Auto Layout.
Adopt Auto Layout
Auto Layout is a powerful layout engine that helps you design adaptive layouts with ease. You describe your intent for the positioning of elements in a scene and then let the layout engine determine how best to implement that intent. You describe your intent using constraints—rules that explain where one element should be located relative to another, what size it should be, or which of two elements should shrink first when something reduces the space available for each of them.
In combination with Auto Layout, one of the most useful tools for working with layouts like the one you have is stack view (
UIStackView
). A stack view provides a streamlined interface for laying out a collection of views in either a column or a row. Stack views let you leverage the power of Auto Layout, creating user interfaces that can dynamically adapt to the device’s orientation, screen size, and any changes in the available space.
You can easily wrap your existing interface in a stack view, adding the necessary constraints to make the stack view display properly in different situations.
To add Auto Layout constraints to the meal scene
- Return to the standard editor by clicking the Standard button.Expand the project navigator and utility area by clicking the Navigator and Utilities buttons in the Xcode toolbar.
- While pressing the Shift key on your keyboard, select the text field, label, and button.
- On the bottom right of the canvas, click the Stack button. (Alternatively, choose Editor > Embed In > Stack View.)Xcode wraps the UI elements in a stack view, stacking them together. Xcode analyzes your existing layout to figure out that the items should stack vertically, not horizontally.
- If necessary, open the outline view. Select the Stack View object.
- In the Attributes inspector, type
12
in the Spacing field. Press Return.You’ll notice the UI elements space out vertically, and the stack view growing with them. - On the bottom right of the canvas, open the Pin menu.
- Above “Spacing to nearest neighbor,” click the two horizontal constraints and the top vertical constraint to select them. They become red when they are selected.These constraints indicate spacing to the nearest leading, trailing, and top neighbors. In this context, the term nearest neighbor means the boundary of the closest UI element, which can be the superview, a peer view, or a margin. Because the “Constrain to margins” checkbox is selected, the stack view in this case will be constrained to the left, right and top margins of its superview, leaving a small amount of room from the edge of the screen.
- Type
0
in the left and right boxes, and type60
spacing in the top box. - In the pop-up menu next to Update Frames, choose Items of New Constraints.The Pin menu should look something like this:
- In the Pin menu, click the Add 3 Constraints button.
The meal scene UI should look something like this:
You’ll notice that the text field isn’t stretching to the far edge of the scene like it used to, so you’ll fix that next.
To adjust the text field width in the meal scene
- In your storyboard, select the text field in the meal scene.
- On the bottom right of the canvas, open the Pin menu.
- Above “Spacing to nearest neighbor,” click the two horizontal constraints to select them. They become red when they are selected.
- Type
0
in the left and right boxes. - In the pop-up menu next to Update Frames, choose Items of New Constraints.The Pin menu should look something like this:
- In the Pin menu, click the Add 2 Constraints button.
- With the text field selected, open the Size inspector in the utility area.The Size inspector appears when you select the fifth button from the left in the inspector selector bar. It lets you edit the size and position of an object in your storyboard.
- In the Intrinsic Size field, select Placeholder. (This field is at the bottom of the Size inspector, so you’ll need to scroll down to it.)Text fields are sized based on their contents, which define their intrinsic content size. Intrinsic content size refers to the minimum size needed to display all the content in the view. You can assign UI elements a placeholder intrinsic content size if you need to design a UI for a different size than you can anticipate at design time. Right now, the text field’s only content is its placeholder string, but the actual text a user enters could be longer than that.
The meal scene UI should look something like this:
Checkpoint: Run your app in Simulator. The text field shouldn’t extend past the edge of the screen anymore. You should be able to click inside the text field and enter text using the keyboard (if you’d like, toggle the software keyboard by pressing Command-K). If you rotate the device (Command-Left Arrow or Command-Right Arrow) or run the app on a different device, the text field grows or shrinks to the appropriate size depending on the device’s orientation and screen size. Note that the status bar disappears in landscape orientation.
If you don’t get the behavior you expect, use the Auto Layout debugging features to help you. Click the Resolve Auto Layout Issues icon, and choose Reset to Suggested Constraints to have Xcode update your interface with a valid set of constraints. Or click the Resolve Auto Layout Issues icon and choose Clear Constraints to remove all constraints on the UI elements, and then try following the steps above again.
Although this scene doesn’t do much yet, the basic user interface is there and functional. Making sure your layout is robust and extensible from the start ensures that you have a solid foundation to build upon.