Creating a User Interface
While it’s possible to create programs that don’t need to interact with a user at all (such as a program that controls a traffic light), it’s far more common to create programs that display a user interface of some kind. Typically that means showing a window filled with different items such as labels to display text, text fields to allow the user to type something in, and buttons or pull-down menus to give the user control over the program.
Creating an effective user interface depends entirely on the purpose of your program. A business program typically follows standard conventions with pull-down menus and buttons, but a video game may create a custom interface that may not look anything like a standard OS X program. Ultimately a user interface needs to meet the needs of the user. Given a choice between following standard user interface design conventions or making a user interface easier for the user, focus on the user every time.
To help you better understand user interface design, Apple provides a free document called the OS X Human Interface Guidelines . This document gives a brief overview of what makes a typical OS X user interface work effectively with special emphasis on taking advantage of the latest features of OS X. By doing this, your OS X program will look modern and up to date. Failure to take advantage of the latest OS X features means your program could look dated even if it’s brand new.
In previous chapters you’ve designed simple user interfaces using Xcode. In this chapter, we’ll dig a little deeper into the different parts of Xcode that focus on helping you design user interfaces.
Remember, there is no “perfect” design for a user interface. The “perfect” user interface is one that makes tasks as simple and effortless as possible to the point where the user doesn’t even notice interacting with any user interface whatsoever. A user interface acts as the middleman or translator between you and the program. The goal of any user interface is to make users feel as if they’re communicating and manipulating a program directly.
Understanding User Interface Files
The Cocoa framework defines classes for creating every possible user interface item from a button (the NSButton class) and a text field (NSTextField) to a slider (NSSlider) or a date picker (NSDatePicker). Theoretically, it’s possible to create an entire user interface using nothing but Swift code. However, this can be tedious because you can’t see how your user interface looks until you actually run your program. This can be as clumsy as trying to paint a picture by describing exactly where you need to put a paintbrush on a canvas and the specific angle and direction to move your hand.
Rather than force you to write Swift code to define your user interface, Xcode offers a feature called Interface Builder . The idea behind Interface Builder is that you can design your user interface by dragging and dropping items on to a window.
The advantage of dragging and dropping items to create a user interface means you can see how your user interface looks so you can rapidly adjust and modify it. In addition, by separating the design of your user interface from your Swift code, you can now make changes to your user interface without affecting your Swift code and vice versa.
In the old days when programmers had to write code to create a user interface, modifying the user interface code risked affecting the code that made the program work (and vice versa). That meant modifying a program went slowly because you had to constantly test to make sure your changes didn’t affect another part of your program.
By keeping your user interface isolated from your Swift code, Xcode lets you create reliable programs faster than before. Now you can swap out one user interface and replace it with another one without affecting your code, or you can modify your code without affecting your user interface.
Xcode gives you two choices for how to store your user interface:
An .xib file (which stands for Xcode Interface Builder) typically contains a single window or view of your user interface. A simple program might have one .xib file for its user interface, but a more sophisticated program would likely need several .xib files to store different windows.
A .storyboard file consists of one or more views and segues where a view typically represents a window that appears on the screen and a segue defines the transition from one view to the next.
You can actually combine both .xib and .storyboard files in a single project to create your program’s user interface. Since .storyboard files are used to create iOS apps, .storyboard files are becoming more common for creating OS X user interfaces as well. (Chapter 14 explains more about storyboards and segues.)
The basic component of a user interface is a view, which displays information on the screen. A view can be an entire window or just a box that can display information such as a table, a scrolling list of text, or a picture. Whether you’re using .xib or .storyboard files, user interfaces always consist of one or more views containing other user interface items, such as buttons and text fields.
To display your program’s user interface, you need to click on the .xib or .storyboard file in the Project Navigator pane. Once you’ve selected a user interface file to modify, you can then drag items from the Object Library (in the bottom right corner of the Xcode window) and place it anywhere on your user interface. To view the Object Library, choose View Utilities Show Object Library.
There are two ways to search the Object Library. One way is to simply scroll up and down until you find the item you want. Since the Object Library lists every possible user interface item available, scrolling can be clumsy and slow.
A faster method is to use the search field at the bottom of the Object Library pane as shown in Figure 13-1. Just type part of the name of the user interface item you want to use and the Object Library filters out every item that doesn’t match what you typed.
Figure 13-1. The search field lets you quickly find user interface items in the Object Library
To see how to search the Object Library, follow these steps:
Figure 13-2. When creating a new project, you have the option of using storyboards for your user interface
Figure 13-3. The UIProgram icon represents your user interface window
Figure 13-4. Searching the Object Library for “text”
User Interface Items That Display and Accept Text
Although the Object Library contains a huge number of available items that you can place on a user interface, most items can be grouped into categories by function. Remember, a user interface has three functions:
The simplest way to display information on a user interface is through a label. In the Cocoa framework, a label is based on the NSTextField class. Essentially a label is a text field that you can’t edit. To identify the class of any item in the Object Library, just click on it and a pop-up window appears that describes the item’s purpose and the class it’s based on as shown in Figure 13-5.
Figure 13-5. Identifying the class of a user interface item in the Object Library
Any user interface item based on the NSTextField can be used to display and accept text, although it’s more common to use a label for displaying text and any other type of text field for letting the user type in text. The list of user interface items based on the NSTextField is shown in Figure 13-6:
Figure 13-6. User interface items based on the NSTextField class
User Interface Items That Restrict Choices
Letting the user enter data in a text field provides maximum flexibility. However, this flexibility also means that your program has no idea what type of data the user might enter. If a program expects the user to type in a number for an age, but the user types in “forty-nine” instead, the program will likely crash because it expects a number but received a word.
Even worse, a program could ask for someone’s age and a user could type a negative number or an outrageously high number such as 239, which is clearly impossible for someone’s age. To ensure that users enter in correct data, you can use a variety of different user interface items that lets the user choose a range of valid options. User interface items that display text (including numbers) choices include:
User interface items that allow the user to select a range of valid numeric options include:
With text options, you need to list all valid options that the user can choose. With numeric options, you just need to list a range of all valid options such as letting the user choose a number between 1 and 100.
User Interface Items That Accept Commands
The most common user interface item is one that accepts commands so the user can control a program. The two most common types of user interface items that accept commands are buttons and menus. Each button or menu item represent a single command, so when the user clicks on a button or menu item, that command tells the program to do something.
Both buttons and menu items allow the view to communicate back to the controller using something called target-action as shown in Figure 13-7. The target is a button or menu item, which triggers an action back in the controller, such as running an IBAction method.
Figure 13-7. Buttons and menu items let a view communicate back to a controller
User interface buttons are based on the NSButton class. Menu items are based on the NSMenuItem class. The Object Library displays a variety of different types of buttons and menu items, but they all work alike where the button or menu item represents a command. To make that command work, you need to connect the button on the user interface to an IBAction method in a Swift file.
User Interface Items That Groups Items
One type of user interface item does nothing but group and organize other items on the user interface, such as displaying a box around related buttons or text. These user interface items are more decorative so you likely won’t need to connect them to Swift code using IBOutlets or IBAction methods. Some examples of items that group and organize other user interface items include:
Figure 13-8. A Tab View can group two or more groups of related items in the same box
Although the Object Library contains many other items, they typically fall in one of these four categories:
Using Constraints in Auto Layout
No matter what type of items you place on a user interface, you need to consider what happens if the user resizes the window. A window that’s too big might leave too much empty space on the user interface. A window that’s too small might cut off items as shown in Figure 13-9.
Figure 13-9. A user interface that doesn’t adapt when the user resizes a window risks cutting off items
There are two ways to make sure a user interface remains usable when the user resizes a window. First, you can define minimum and maximum sizes for a window to keep a window from shrinking or expanding too much. Second, you can set constraints on individual items that define the distance between neighboring items and the edges of the window.
In most cases, you can use both methods. That way you can define a minimum and maximum size for a window, and define how items on your user interface should adapt to changes in the window size.
A window displays your program’s user interface on the screen. Xcode lets you define the following for a window as shown in Figure 13-10 :
Figure 13-10. The Size Inspector lets you define the size of a window
To define the size of a window of an .xib file in Xcode, follow these steps:
Figure 13-11. The Hide Document Outline icon
Figure 13-12. The bottom icon represents your user interface window
Windows stored in .storyboard files work slightly differently than .xib files. To define the size of a window of a .storyboard file in Xcode, follow these steps:
Figure 13-13. The View Controller defines your user interface window
Xcode gives you two ways to change the size of a window. First, you can drag a side or corner of the window (or view controller) using the mouse. Second, you can click in the Width and Height text fields next to the Size label to choose a precise size for your window’s width and height as shown in Figure 13-14 .
Figure 13-14. The View Controller defines your user interface window
To define the minimum and/or maximum size of a window involves a two-step process. First, you need to select the Minimum Size and/or Maximum Size check box. Second, you need to type or choose a width and height to define the minimum or maximum size for your window as shown in Figure 13-15.
Figure 13-15. Defining the minimum and maximum size for a window
Finally, you can define the initial position of a window when it first appears. You can do this by either dragging on the window icon on the simulated screen or by typing in an X and Y value into the Initial Position text fields as shown in Figure 13-16.
Figure 13-16. Defining the initial position of a window
The two pop-up menus underneath the simulated screen lets you define how to determine the initial position of a window:
To see how you can specify a window’s position and minimum/maximum size, let’s create a simple program and modify its window.
Figure 13-17. Specifying a minimum, maximum, and initial position of a window
Placing Constraints on User Interface Items
Defining a minimum size for a window can keep the user from shrinking a window so small that it cuts off the items that appear on the user interface. However, what happens if the user expands a window? Then the items in the window should ideally adjust their position to adapt to the expanded window size.
Constraints define the distance between two items such as between a button and the edge of the window or between two buttons. Xcode gives you three ways to place constraints on a user interface item:
Figure 13-18. The Align, Pin, and Resolve Auto Layout Issues icons
To use the Control-drag method to place a constraint, follow these steps:
Figure 13-19. Releasing the Control key and the mouse displays a pop-up window
Depending on the direction you Control-drag the mouse, you’ll see different options in the pop-up window.
Direction to window edge |
Constraint Option |
---|---|
Up |
Top Space to Container |
Bottom |
Bottom Space to Container |
Right |
Trailing Space to Container |
Left |
Leading Space to Container |
Besides Control-dragging to a window edge, you can also Control-drag from one user interface item over another user interface item. Doing this lets you define the distance between two items on the user interface such as the distance between two buttons or one button and a text field.
When you Control-drag the mouse over another user interface item, a pop-up window appears. If you’re defining the distance between two items that are side by side, the pop-up window will display the Horizontal Spacing option. If you’re defining the distance between two items that are stacked one on top of another, the pop-up window will display the Vertical Spacing option.
Direction to another item |
Constraint Option |
---|---|
Left/Right |
Horizontal Spacing |
Up/Down |
Vertical Spacing |
The Control-drag method lets you place constraints visually on different user interface items. Another way to define constraints is to click on the user interface item you want to constrain, and then click on the Pin icon to display a pop-up window. To define constraints through the Pin icon, follow these steps:
Figure 13-20. The Pin icon displays a pop-up window of constraints
The Pin pop-up window lets you define additional types of constraints for your selected user interface item:
A third way to define constraints is to let Xcode choose constraints for you. This lets you add constraints quickly, but at the risk that Xcode may not define constraints correctly. Fortunately, you can always edit constraints later.
To let Xcode choose constraints, follow these steps:
Figure 13-21. The Resolve Auto Layout Issues pop-up window
If you choose the options in the top half of the window, you’ll affect only the selected user interface item. If you choose the options in the bottom half of the window, you’ll affect all user interface items whether on the currently displayed window whether you selected them or not.
Remember, adding constraints can be a trial and error process of defining a constraint and seeing how it works before modifying or deleting it altogether. As you add constraints, Xcode displays constraint lines around your user interface item. If Xcode doesn’t think you have enough constraints, all constraints on that item will appear as orange. The moment Xcode thinks you have enough constraints on an item, the constraints will appear in blue.
To see how constraints work with user interface items, follow these steps:
Figure 13-22. Connecting a constraint to a window edge
Editing Constraints
Once you’ve defined one or more constraints, you can always delete or edit existing constraints. To delete a constraint, you have several options:
You can also delete or clear all constraints from a single user interface item or from all items on the currently displayed user interface. To do this, you have two options:
With either option, you’ll see a menu divided in a top half and a bottom half as shown in Figure 13-23. Clicking Clear Constraints in the top half clears constraints only from any currently selected items. Clicking Clear Constraints in the bottom half clears constraints from all items in the currently displayed user interface whether you selected them or not.
Figure 13-23. A pop-up window lets you modify a constraint
Rather than delete a constraint, you can edit it. Editing lets you modify how it behaves. Three values you can modify about a constraint include:
To edit a constraint, follow these steps:
Figure 13-24. Viewing a list of defined constraints in the Size Inspector pane
Figure 13-25. A pop-up window lets you modify a constraint
Notice that to the right of the Constant: label, there’s a pop-up menu showing an equal sign (=). If you click on this pop-up menu, you can select greater than or equal to, less than or equal to, or equal to.
Further to the right of the Constant: label is a drop-down field that displays a number. If you click on the downward-pointing arrow, you’ll be able to choose between three options:
Keep in mind that a fixed value or Canvas Value may behave differently on different size monitors. You may need to experiment until you find the right value for your particular user interface.
Priorities are used to resolve conflicts between two or more constraints that may contradict each other, such as one constraint keeping a button pinned to the right edge of a window and a second constraint keeping the same button pinned to the left edge of a window while a third constraint keeps the button a fixed width. By modifying priorities, you can make sure your constraints don’t conflict.
Finding the right combination of constraints can be tedious and frustrating at times. To simplify setting constraints, Xcode offers two ways to define constraints for you:
When you first define constraints, Xcode displays them in orange to let you know that you don’t have enough constraints to define the position of an item on your user interface. Once you’ve defined enough constraints to specify a position, then Xcode displays constraints in blue.
If you define constraints, you may see a dotted orange line that represents the outline of your currently selected item. This dotted line is a frame and shows where your item will appear when you actually run your program.
To move an item into its proper location, you need to choose either Editor Resolve Auto Layout Issues Update Frames, or click on the Resolve Auto Layout Issues icon in the bottom right corner of the Xcode window and choose Update Frames (see Figure 13-23).
To see how Xcode can automatically define constraints, follow these steps:
Figure 13-26. Xcode automatically adds all necessary constraints
Defining Constraints in an OS X Program
To fully understand how constraints work, you need to see how they work in an actual program. Then you can see how your user interface adjusts each time you resize its window. In this sample program, we’ll define relationships constraints for a push button and a text field, and also define an aspect ratio for an image.
Earlier in this chapter you created an OS X project called UIProgram so we’ll use that to see how constraints work:
Figure 13-27. The user interface of the InheritProgram
While this user interface may look fine right now, it will look awful as soon as the user resizes the window. Choose Product Run and then resize the window to see how shrinking the window cuts off or hides items on the user interface. Now expand the size of the window and notice all the empty space inside the expanded window. Exit out of your program by choosing UIProgram Quit UIProgram.
First, let’s define the window’s minimum size by following these steps:
Figure 13-28. Adjusting the size of the user interface window
By defining a minimum window size, you’ve kept your user interface from getting cut off or having items disappear if the user shrinks the window too small. Now let’s add constraints to make the user interface adapt if the user expands the window size .
Figure 13-29. Adjusting the size of the user interface window
Figure 13-30. Constraints on the text field
Figure 13-31. Defining an aspect ratio constraint
Summary
Your program’s user interface determines how people interact with your program. Every user interface needs to display information, retrieve information from the user, and allow the user to choose commands. Ideally a user interface should focus more on using your program and less on figuring out how the user interface works.
The Object Library displays all possible items you can add to your user interface whether you use .xib or .storyboard files. To help you find items in the Object Library, you can type all or part of a word in the search field at the bottom of the Object Library.
Constraints help keep your user interface looking good no matter how the user resizes your program’s windows. The two basic types of constraints involve the following:
You can define constraints on your own, let Xcode define constraints, or use a combination of both. Defining constraints may be a trial and error process until your user interface adapts to resizing windows exactly the way you want.