Building Our User Interface

That white box in the Simulator is our app. It’s not much, but then again, we haven’t done anything yet, so let’s start building it. Press Stop in Xcode to stop the simulated app, and then take a look at the project in Xcode.

images/userinterface/xcode-project-files.png

If the File Navigator isn’t already showing on the left side of the project window, bring it up with the folder icon in the Navigator area (1). The File Navigator uses a tree-style hierarchy with a blue Xcode document at the top, representing the project itself as the root. Under this are files and folders. The folder icons are groups that collect related files, such as the views and logic classes for one part of the app; groups don’t usually represent actual directories on the filesystem. We can expand all the groups to see the contents of the project, as shown in the figure here.

Different project templates will set us up with different files. For the view-based app, we get two source code files in the PragmaticPodcasts group, along with a Main.storyboard, a LaunchScreen.storyboard, and an Assets.xcassets. These are the files we’ll be editing. There are also a few helper files like Info.plist, but we won’t need to edit them directly. The PragmaticPodcastsTests group is where we will write unit tests to validate our code, something we’ll do in Chapter 6, Testing the App. Ditto for PragmaticPodcastsUITests, which can test the purely UI parts of our app. Finally, the Products group shows the files our build will create: in this case, PragmaticPodcasts.app for the app, plus PragmaticPodcastsTests.xctest and PragmaticPodcasts- UITests.xctest for the runnable unit tests. Files shown in red indicate they haven’t been built yet; PragmaticPodcasts.app is red in the preceding figure because, although we’ve run it in the Simulator, we haven’t built it for the actual device yet.

Editing Storyboards with Interface Builder

We said at the outset that iOS development starts with the user interface. By focusing on what users see and how they interact with it, we keep our focus on the user experience and not on the data models and logic behind the scenes. We typically build our user interfaces visually and store them in storyboards. The project has one such file, Main.storyboard, so let’s click it.

When we click Main.storyboard, the Editor Area switches to a graphical view called Interface Builder, or IB for short. In iOS, IB works with user interface documents called storyboards. Just like in movie-making, where a storyboard is a process used to plan out a sequence of shots in a movie or TV show, the storyboard of an iOS app shows the progression through the different views the app will present. The initial storyboard looks like the following figure.

images/userinterface/xcode-storyboard-empty.png

Our app uses a single view, so we follow the right-pointing arrow (which indicates where the app starts) into a rectangle that represents the visible area of the screen. This is our app’s one view; if we were building a navigation-style app, there would be one view rectangle for each screen of the navigation. Click the view to show a header box with three icons. These are proxy objects that represent objects that will work with the view at runtime: a yellow circle View Controller that contains logic to respond to events and update the view; an orange cube First Responder that represents the ability to handle events; and an orange square Exit, used for when we back out of views in navigation apps (something we’ll visit in a later chapter).

images/userinterface/ib-scene-list.png

At the bottom left of the Editor area, next to the “View As:” label, IB shows a little view disclosure button. Click this to show and hide the scene list (shown here), which shows each “scene” of the storyboard and its contents as a tree structure. Currently, our one scene has the proxy objects, and inside the view controller, we find two layout objects and a “view.” This view is the big rectangle in the UI; as we add UI elements such as buttons and labels, the scene’s tree list will show them as children of this view.

Speaking of the view, notice that it’s a tall rectangle in more or less the shape of an iPhone SE screen (or whatever device is selected in the scheme selector). In the bottom of the Editor area, next to View As, notice the name of the model “iPhone SE.” This is actually a button; click it to show a small gallery of the various iOS device sizes, from the huge iPad Pro 12.9" down to the little iPhone 4s. The currently selected device and its orientation (portrait or landscape) will be shown in blue. If you choose an iPad model, the interface becomes a set of more detailed pop-ups; use the Device pop-up to get back to an iPhone model. Selecting different devices or orientations will change the size of the view rectangle in the content view, something that will be very important to us soon.

images/userinterface/ib-device-map.png

Next to the name of the device, there’s a little legend that looks like “(w:C h:R).” These represent the size class of the device in that orientation. The labels “w” and ”h” represent “width” and “height,” respectively, and the values “C” and “R” mean “compact” and “regular.” “Compact” means an axis where we don’t have a lot of space to work with, like the width of an iPhone in portrait orientation. We’ll be able to use these later to customize our UI for different devices and orientations.

Adding UI Components

So let’s start building our user interface. Since we already know how to make a media player, we’ll build that scene first, and later we’ll build scenes for listing podcasts and their episodes.

To add components to our storyboard, use the toolbar to show the Utility area on the right (if it’s not already showing), and find the library pane at the bottom right. There’s a mini toolbar here that should default to showing user interface objects; if not, click the little icon of a square in a circle (or press 3). The bottom of the pane has a button to toggle between list and icon views for the objects, and a search filter to find objects by name. Scroll down through this pane to find the icon that just says Button; we can tap once on any of the objects to get its name, class, and description to appear in a pop-over. Drag the button from the Object Library into the upper left of the iPhone-sized view in IB. This will create a plain button.

images/userinterface/xcode-plain-button.png

It leaves a lot to the imagination, huh? Without the edge and background decorations of earlier versions of iOS, it doesn’t necessarily look like a button at all. It could easily be mistaken for a text label.

That’s somewhat by design. iOS’ “flat” UI look has three stated themes: deference, clarity, and depth. The first of these, deference, means that the UI appearance focuses attention on our content rather than competing with a bunch of pseudo-realistic effects.

So maybe our problem is a lack of content. iOS expects us to tell the user what’s going on in our app, and we’re not holding up our end of the deal yet. Let’s fix that. First, we’ll say what the button does. Double-click the button to change its name to Play. Now it says what it does, but it still doesn’t exactly feel button-y.

images/userinterface/ib-label-icon.png

Maybe we can fix that by contrasting the blue text of the button with a plain label. Back in the Object Library at the lower right, find the Label object, and drag a label to the upper right. Change its text to “0:00.” As you probably guessed, we will be using this to show the current time of the item that’s playing.

images/userinterface/ib-attribute-inspector.png

Our user interface elements are kind of boring and small for a media player screen. That’s because they’re the default size, font, and color. We can change that easily enough. Select the button, and then bring up the Attributes Inspector in the right pane with the mini toolbar button that looks like the playhead of a value slider (or just use the keyboard shortcut 4). This brings up an inspector with many values we can change for the button: its color, font, title text, and more. Just use up and down arrows on the Font line to increase the size to 30.0. The larger text in the button won’t fit anymore and will change to “...,” so use the handles on the button to resize it until it says “Play” again.

Select the “0:00” label and change its font size to 30.0 as well. While we’re working with labels, let’s add another one for the current track’s title. Drag a new label out from the library, and place it below the Play button. We can leave this label at the default size; just change the default text from “Label” to “Track Title.” The view should look something like the following figure:

images/userinterface/xcode-button-and-labels.png

Go ahead and click the Run button to run this app again in the iOS Simulator. This launches our app in the simulated iPhone and shows our button and labels. Progress!

Alas, there’s a catch. We’ve only been thinking about our user interface when the user is holding the phone in portrait view. What happens if the user holds it sideways? Let’s find out. Rotate to landscape with Rotate Left and Rotate Right items in the Hardware menu ( and , respectively). The spacing between the components is the same, but now that’s wrong, because the time label is no longer in the upper right—it kind of ends up in the middle of the screen.

Press Stop in Xcode, and let’s look at the storyboard again. It turns out this is a problem we could have seen coming. Under View As, select the landscape orientation. The storyboard shows us what the UI looks like when it’s sideways, as shown here:

images/userinterface/xcode-button-and-labels-landscape-no-autolayout.png

Even in portrait, the time label will be in the wrong place on other iPhone models, like the larger 7 and 7 Plus. The problem is that when we dropped these UI components in the view, Xcode could only know their current coordinates and sizes. We may have meant to say “keep the label aligned to the right side,” but there was no way for Xcode to know that. It could just as well have assumed we wanted a constant distance from the button, or just whatever x-coordinate we happened to drag it to.

What we need now is a way to tell Xcode where we want the label to go on different size screens and in different orientations. Lucky for us, Xcode is up to the task.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset