Hour 9. Using Advanced Interface Objects and Views


What You’ll Learn This Hour:

Image How to use segmented controls (a.k.a. button bars)

Image Ways of inputting Boolean values via switches

Image How to include web content within your application

Image The use of scrolling views to overcome screen-size limitations

Image Creating orderly, organized content with stack views


After the past few lessons, you now have a good understanding of the basic iOS interface elements, but we’ve only just scratched the surface. Additional user input features are available to help a user quickly choose between several predefined options. After all, there’s no point in typing when a touch is enough. This hour’s lesson picks up where the last left off, providing you with hands-on experience with a new set of user input options that go beyond fields, buttons, and sliders.

In addition, we look at three new views you can use to present data to the user: web, scrolling, and stack views. These features make it possible to create applications that can extend beyond the hardware boundaries of your device’s screen, automatically create rows and columns of content, and include information from remote web servers.

User Input and Output (Continued)

When I set out to write this book, I originally dedicated a couple of hours to the iOS interface widgets (fields, buttons, and so on). After we got started, however, it became apparent that for learning to develop on iOS, the interface was not something to gloss over. The interface options are what makes the device so enjoyable to use and what gives you, the developer, a truly rich canvas to work with. You’ll still need to come up with ideas for what your application will do, but the interface can be the deciding factor in whether your vision “clicks” with its intended audience.

In the past two hours, you learned about fields, sliders, steppers, labels, and images as input and output options. In this lesson, you explore two new input options for handling discrete values, along with three new view types that extend the information you can display to web pages and beyond.

Switches

In most traditional desktop applications, the choice between something being active or inactive is made by checking or unchecking a check box or by choosing between radio buttons. In iOS, Apple has chosen to abandon these options in favor of switches and segmented controls. Switches (UISwitch) present a simple on/off user interface (UI) element that resembles a traditional physical toggle switch, as shown in Figure 9.1. Switches have few configurable options and should be used for handling Boolean values.

Image

FIGURE 9.1 Use switches to provide on/off input options to your user.


Note

Check boxes and radio buttons, although not part of the iOS UI Library, can be created with the UIButton class using the button states and custom button images. Apple provides the flexibility to customize to your heart’s content—but sticking with controls your users will find familiar will often provide superior usability.


To work with the switch, we’ll make use of its Value Changed event to detect a toggle of the switch and then read its current value via the on variable property.

The value returned when checking a switch is a Boolean, meaning that we can compare it to true or false to determine its state, or evaluate the result directly in a conditional statement.

For example, to check whether a switch mySwitch is turned on, we can use code similar to this:

if (mySwitch.on) { <switch is on> } else { <switch is off> }

Segmented Controls

When user input needs to extend beyond just a Boolean value, you can use a segmented control (UISegmentedControl). Segmented controls present a linear line of buttons (sometimes referred to as a button bar), within which a single button can be active within the bar, as shown in Figure 9.2.

Image

FIGURE 9.2 Segmented controls combine multiple buttons into a single control.

Segmented controls, when used according to Apple guidelines, result in a change in what the user sees onscreen. They are often used to choose between categories of information or to switch between the display of application screens, such as configuration and results screens. For just choosing from a list of values where no immediate visual change takes place, the Picker object should be used instead. We look at this feature in Hour 12, “Making Choices with Toolbars and Pickers.”


Note

Apple recommends using segmented controls to update the information visible in a view. If the change, however, means altering everything onscreen, you are probably better off switching between multiple independent views using a toolbar or tab bar. We start looking at the multiview approach in Hour 11, “Implementing Multiple Scenes and Popovers.”


Handling interactions with a segmented control is very similar to handling them with the toggle switch. We’ll watch for the Value Changed event and determine the currently selected button through the selectedSegmentIndex, which returns the number of the button chosen (starting with 0, from left to right).

We can combine the index with the object’s instance method titleForSegmentAtIndex to work directly with the titles assigned to each segment. To retrieve the name of the currently selected button in a segmented control called mySegment, we could use the following code fragment:

mySegment.titleForSegmentAtIndex(mySegment.selectedSegmentIndex)

We use this technique later in the lesson.

Web Views

In the previous applications that you’ve built, you’ve used the typical iOS view: an instance of UIView to hold your controls, content, and images. This is the view you will use most often in your apps, but it isn’t the only view supported in iOS. A web view, or UIWebView, provides advanced features that open up a whole new range of possibilities in your apps.


Tip

In Hour 7, “Working with Text, Keyboards, and Buttons,” you used another view type, UITextView, which provides basic text input and output, and which straddles the line between an input mechanism and what we’ll typically refer to as a view.


Think of a web view as a borderless Safari window that you can add to your applications and control programmatically. You can present HTML, load web pages, and offer pinching and zooming gestures, all “for free,” using this class.

Supported Content Types

You can also use web views to display a wide range of files, without needing to know anything about the file formats:

Image HTML, images, and CSS

Image Word documents (.doc/.docx)

Image Excel spreadsheets (.xls/.xlsx)

Image Keynote presentations (.key)

Image Numbers spreadsheets (.numbers)

Image Pages documents (.pages)

Image PDF files (.pdf)

Image PowerPoint presentations (.ppt/.pptx)

You can add these files as resources to your project and display them within a web view, access them on remote servers, or read them from an iDevice’s file storage (which you learn about in Hour 15, “Reading and Writing Application Data”).


Need Safari? Use Safari!

Beginning in iOS 9, you can display a “mini” version of Safari (complete with all your cookies and form-fill information) within your applications. This is useful when you want to enable users to access a website without having to build your own browser or exit your application and start Safari. You’ll learn more about this capability in Hour 20, “Interacting with Other iOS Services.”


Loading Remote Content with NSURL, NSURLRequest, and loadRequest

Web views implement a method called loadRequest that you can use to load an arbitrary URL; unfortunately, however, you can’t just pass it a string and expect it to work.

To load content into a web view, you’ll often use NSURL and NSURLRequest. These two classes enable you to manipulate URLs and prepare them to be used as a request for a remote resource. You first create an instance of an NSURL object, most often from a string using the NSURL convenience initialization method. For example, to create an NSURL that stores the address for Apple’s website, you could use the following:

var appleURL: NSURL
appleURL=NSURL(string: "https://www.apple.com")!

Notice the exclamation mark at the end of that line? The ! indicates that we’re “unwrapping” (accessing) the value that precedes it (that is, the object returned by the NSURL initialization method). Why is this necessary? If you use the Xcode documentation for NSURL, you’ll see that it may return nil. In other words, it may return the NSURL object we want, or, if something is wrong with the string, it may return nothing at all! Xcode wants us (very much) to understand and acknowledge this, so it forces us to explicitly “unwrap” the value by adding the !. If you fail to add the exclamation mark, you’ll get an error, and Xcode will offer to add it for you.

Once the NSURL object is created, you need to create an NSURLRequest object that can be passed to a web view and loaded. To return an NSURLRequest from an NSURL object, we can use the NSURLRequest convenience initialization method that, given an NSURL, returns the corresponding request object:

NSURLRequest(URL:appleURL)

Finally, this value is passed to the loadRequest method of the web view, which then takes over and handles loading the process. Putting all the pieces together, loading Apple’s website into a preexisting web view called appleView looks like this:

var appleURL: NSURL
appleURL=NSURL(string: "https://www.apple.com")!
appleView.loadRequest(NSURLRequest(URL:appleURL))

We implement web views in this hour’s first project, so you’ll soon have a chance to put this to use.


More Convenience, Less Consistency

Recall that convenience initialization methods usually require an “external” named parameter (such as string for creating an NSURL object, or URL for an NSURLRequest) as the first argument:

NSURL(string: "https://www.apple.com")
NSURLRequest(URL:appleURL)

It can be a bit disconcerting to see these methods with their named parameters popping up around other single-parameter methods without this required syntax.



Tip

Another way that you get content into your application is by loading HTML directly into a web view. For example, if you generate HTML content in a string called myHTML, you can use the loadHTMLString:baseURL method of a web view to load the HTML content and display it. Assuming a web view called htmlView, you might write this as follows:

htmlView.loadHTMLString(myHTML, baseURL: nil)


Scrolling Views

You’ve certainly used applications that display more information than what fits on a single screen; in these cases, what happens? Chances are, the application allows you to scroll to access additional content. Often, this is managed through a scrolling view, or UIScrollView. Scrolling views, as their name suggests, provide scrolling features and can display more than a single screen’s worth of information.

Unfortunately, Apple has gone about halfway toward making scrolling views something that you can add to your projects using the Interface Builder (IB) tools. You can add the view, but until you add a line of code to your application, it won’t scroll.

Stack Views

As you build-content rich applications, you’ll eventually reach a state where you just want to add objects to your screen and have them displayed in a nice orderly fashion—without dealing with spacing issues and complex calculations. Stack views (UIStackView) do exactly that. Stack views can be oriented either horizontally or vertically, and simply stack up the content that you add to them.

Want a row of 5 icons spaced 10 points apart? Add the icons to a horizontal stack view and set the spacing to 10. Want a grid of icons? Add several horizontal stack views of icons to a vertical stack view. Combining these views with the Auto Layout system (Hour 16, “Building Responsive User Interfaces”), you’ll be able to create layouts featuring lots of objects that adapt to different sized devices, and don’t require tons of code.

We close out this hour’s lesson with a quick example (a single line of code) that embeds multiple UIStackView instances in a UIScrollView to create a scrolling grid of icons.

Using Switches, Segmented Controls, and Web Views

As you’ve probably noticed by now, we prefer to work on examples that do something. It’s one thing to show a few lines of code in a chapter and say “this will do <blah>,” but it’s another to take a collection of features and combine them in a way that results in a working application. In some cases, the former approach is unavoidable, but this isn’t one of them. Our first hands-on example makes use of web views, a segmented control, and a toggle switch.

Implementation Overview

In this project, we create an application that displays flower photographs and flower information fetched from the website TeachYourselfiOS.info. The application enables a user to touch a flower color within a segmented control (UISegmentedControl), resulting in a flower of that color being fetched and displayed from the site in a web view (UIWebView). The user can then use a toggle switch (UISwitch) to show and hide a second web view that contains details about the flower being displayed. Finally, a standard button (UIButton) enables the user to fetch another flower photo of the currently selected color from the site. The result should look very much like Figure 9.3.

Image

FIGURE 9.3 The finished application will make use of a segmented control, a switch, and two web views.

Setting Up the Project

This project will, once again, use the Single View Application template we’re starting to love. If it isn’t already running, launch Xcode, and then create a new project using the same settings as in the previous hours. Call this project FlowerWeb.

You should now be accustomed to what happens next. Xcode sets up the project and creates the default view in Main.storyboard and a view controller class named ViewController. We’ll start as we always do: planning the variables, outlets, and actions we need in the view controller.

Planning the Variables and Connections

To create the web-based image viewer, we need three outlets and two actions. The segmented control will be connecting to variable property called colorChoice because we’ll use it to choose which color is displayed. The web view that contains the flower will be connected to flowerView, and the associated details web view to flowerDetailView.

For the actions, the application must do two things: get and display a flower image, which we’ll define as the action method getFlower; and toggle the flower details on and off, something we’ll handle with a toggleFlowerDetail action method.


Why Don’t We Need an Outlet for the Switch?

We don’t need to include an outlet for the switch because we are connecting its Value Changed event to the toggleFlowerDetail method. When the method is called, the sender parameter sent to the method references the switch, so we can just use sender to determine whether the switch is on or off.

If we have more than one control using toggleFlowerDetail, it is helpful to define outlets to differentiate between them; in this case, however, sender suffices. This is our first use of sender, so pay attention. It can help save you the trouble of creating properties/instance variables in cases such as this.


Designing the Interface

By now, this process should seem a bit familiar. We’ve defined the outlets and actions, so it’s time to build the UI. Prepare your Xcode workspace for developing the UI: Choose the Main.storyboard file to open the IB editor, and then close the project navigator, if necessary, to make room on your display.

As with the previous projects, I recommend selecting the view controller for your scene and then using the Attributes Inspector to set the simulated screen size to something familiar, like the 4.7-inch iPhone. Once your workspace is configured, we can get down to the design.

We begin by adding the segmented control.

Adding a Segmented Control

To add a segmented control to the user interface, open the Object Library (View, Utilities, Object Library), find the segmented control (UISegmentedControl) object, and drag it into the view. Position the control near the top of the view in the center. Because this control is ultimately used to choose colors, click and drag a label (UILabel) into the view, as well, position it above the segmented control, and change it to read Choose a Flower Color:. Your view should now resemble Figure 9.4.

Image

FIGURE 9.4 The default segmented control has two buttons: First and Second.

By default, the segmented control has two segments, titled First and Second. You can double-click these titles and edit them directly in the view, but that doesn’t quite get us what we need.

For this project, we need a control that has four segments, each labeled with a color: Red, Blue, Yellow, and Green. These are the colors that we can request from the TeachYourselfiOS.info website for displaying. Obviously, we need to add a few more segments to the control before all the choices can be represented.

Adding and Configuring Segments

The number of segments displayed in the segmented control is configurable in the Attributes Inspector for the object. Select the control that you’ve added to the view, and then press Option-Command-4 to open the Attributes Inspector, shown in Figure 9.5.

Image

FIGURE 9.5 Use the Attributes Inspector for the segmented control to increase the number of segments displayed.

Using the Segments field, increase the number from 2 to 4. You should immediately see the new segments displayed. Notice that directly below where you set the number of segments in the inspector is a drop-down with entries for each segment you’ve added. You can choose a segment in this drop-down and then specify its title in the Title field. You can even add image resources and have them displayed within each segment.


Note

Note that the first segment is segment 0, the next is segment 1, and so on. It’s important to keep this in mind when you’re checking to see which segment is selected. The first segment is not segment 1, as you might assume.


Update the four segments in the control so that the colors Red, Blue, Yellow, and Green are represented. The segmented control should now have titles for all the colors and a corresponding label to help the user understand its purpose.


Note

iPad developers who want to take advantage of their extended screen space might try adding a few more segments to the segmented control. The colors violet and magenta can be added and will be automatically recognized by the TeachYourselfiOS.info site.



Segmented Control Appearance: iOS 6 Versus iOS 7+

In iOS 7 and later, a segmented control is a segmented control; consistency is king.

If you’re developing for iOS 6, however, segmented controls have more appearance customizations. In addition to the usual color options and controls available in the Attributes Inspector, you have three choices for presenting the segmented control. Use the Style drop-down menu to choose between Plain, Bordered, and Bar.


Sizing the Control

Chances are, the control you’ve set up doesn’t quite look right in the view. To size the control to aesthetically pleasing dimensions, use the selection handles on the sides of the control to stretch and shrink it appropriately. You can even optimize the size of individual segments by setting them to a fixed width using the Segmented Control Size options in the Size Inspector (Option-Command-5), as shown in Figure 9.6, or set the Auto-Size mode so that the segments are scaled according to the size of their content.

Image

FIGURE 9.6 You can use the Size Inspector to size each segment individually, if desired.

Adding a Switch

The next UI element we’ll add is the switch (UISwitch). In our application, the switch has one role: to toggle a web view that displays details about the flower (flowerDetailView) on and off. Add the switch to the view by dragging the switch object from the Object Library into the view. Position it along the right side of the screen, just under the segmented control.

As with the segmented control, providing some basic user instruction through an onscreen label can be helpful. Drag a label (UILabel) into the view and position it to the left of the switch. Change the text to read Show Photo Details:. Your view should now resemble Figure 9.7, but your switch will likely show up as on.

Image

FIGURE 9.7 Add a switch to toggle flower details on and off.

Setting the Default State

I know you’re getting used to many of the different configuration options for the controls we use, but in this case, the switch has only a few options: whether the default state is on or off and what custom tints (if any) should be applied in the on state and to the “thumb” (the little round thing) of the switch.

The switch that you added to the view is set to on. We want to change it so that it is off by default. To change the default state, select the object and open the Attributes Inspector (Option-Command-4). Using the State pop-up menu (see Figure 9.7), change the default state to off.

Adding the Web Views

The application that we’re building relies on two different web views. One displays the flower image itself; the other view (which can be toggled on and off) shows details about the image. The details view will be overlaid on top of the image itself, so let’s start by adding the main view, flowerView.

To add a web view (UIWebView) to your application, locate it in the Object Library and drag it into your view. The web view will display a resizable rectangle that you can drag and position anywhere you want. Because this is the view that the flower image is shown in, position it to fall about halfway down the screen, and then resize it so that it is the same width as the device screen and so that it covers the lower portion of the view entirely.

Repeat this to add a second web view for the flower details (flowerDetailView). This time, size the view so that it is about half an inch high and locate it at the very bottom of the screen, over top of the flower view, as shown in Figure 9.8. Remember that you can drag items in the document outline to change their ordering. The closer an element is to the top of the list, the further “back” it is.

Image

FIGURE 9.8 Add two web views (UIWebView) to your screen, and then position them as shown here.

Setting the Web View Attributes

Web views, surprisingly, have few attributes that you can configure, but what is available can be very important. To access the web view attributes, select one of the views you added, and then press Open-Command-4 to open the Attributes Inspector (see Figure 9.9).

Image

FIGURE 9.9 Configure how the web view will behave.

You can select from three types of settings: Scaling, Detection (Phone Numbers, Addresses, Events, Links), and a generic Options. If you select Scales Page to Fit under Scaling, large pages are scaled to fit in the size of the area you’ve defined. If you use Detection options, the iOS data detectors go to work and underline items that it has decided are phone numbers, addresses, dates, or additional web links. The Options settings apply to media playback—whether you can use AirPlay, how media plays in your web view (inline or not)—as well as to how web pages render (most do it incrementally) and whether pages are allowed to display a keyboard automatically.

For the main flower view, we absolutely want the images to be scaled to fit within the view. Select the web view, and then use the Attributes Inspector to choose the Scales Page to Fit option.

For the second view, we do not want scaling to be set, so select the web view where the application will be showing the flower details and use the Attributes Inspector to ensure that no scaling takes place. You might also want to change the view attributes for the detail view to have an alpha value of around 0.65. This creates a nice translucency effect when the details are displayed on top of the photograph.


Caution: Understand the Effects of Scaling

Scaling doesn’t necessarily do what you might expect for “small” web pages. If you display a page with only the text Hello World on it in a scaled web view, you might expect the text to be shown to fill the web view. Instead, the text will be tiny. The web view assumes that the text is part of a larger page and scales it down rather than making it appear bigger.

If you happen to have control of the web page itself, you can add a "viewport" meta tag to tell Safari how wide (in pixels) the full page is, as follows:

<meta name="viewport" content="width=320"/>

With the tough stuff out of the way, we just have one more finishing touch to put on the interface, and then we’re ready to code.


Finishing the Interface

The only functional piece currently missing from our interface is a button (UIButton) that we can use to manually trigger the getFlower method anytime we want. Without the button, we have to switch between colors using the segmented control if we want to see a new flower image. This button does nothing more than trigger an action (getFlower), something you’ve done repeatedly in the past few hours, so this should be quite easy for you by now.

Drag a button into the view, positioning it in the center of the screen above the web views. Edit the button title to read Get New Photo. We’re done. You know what that means: time to wire the interface to the code.


Tip

Although your interface may be functionally complete, you might want to select the view itself and set a background color. Keep your interfaces clean and friendly.


Creating and Connecting the Outlets and Actions

We have quite a few interface elements to connect for this project. Our segmented control, switch, button, and web views all need the proper connections to the view controller. Here’s what we’ll use.

Starting with the outlets:

Image Segmented control for choosing colors (UISegmentedControl): colorChoice

Image Main flower web view (UIWebView): flowerView

Image Flower detail web view (UIWebView): flowerDetailView

And then the actions:

Image Fetch a new flower using the Get New Flower button: getFlower

Image Turn the flower detail view on and off with the UISwitch: toggleFlowerDetail

Okay, the same old story: Prepare your workspace by making sure that the Main.storyboard file is selected and then opening the assistant editor. Hide the project navigator and document outline if you need space.

I assume you’re getting pretty familiar with this process, so we’ll move quickly through the connections here and in later hours. After all, it’s just click, drag, and connect.

Adding the Outlets

Begin by Control-dragging from the segmented color button control to the line following the class line in the ViewController.swift file. When prompted, configure the connection as an outlet and its name as colorChoice, leaving the other values set to the defaults. This gives us an easy way to get the currently selected color in our code.

Continue building the rest of the outlets, connecting the main (large) web view to the outlet flowerView by Control-dragging to just below the first @IBOutlet line in ViewController.swift. Finish the outlets by connecting the second web view to flowerDetailView with the same approach, as shown in Figure 9.10.

Image

FIGURE 9.10 Connect the web views to appropriately named outlets.

Adding the Actions

Our UI triggers two action methods. The switch hides and shows details about the flower through the method toggleFlowerDetail, and the standard button loads a new image for us with getFlower. Straightforward, right? It is, but sometimes you need to think beyond the obvious actions users can take and consider what they will expect to happen when they use the interface.

In this application, users are presented with a simple interface. They should immediately recognize that they can choose a color and push a button to get a flower of that color. But shouldn’t the application be smart enough to load a new flower as soon as the user switches the color? Why should the user have to switch the color and then press another button? By connecting the UISegmentedControl’s Value Changed event to the same getFlower method we trigger from the button, we gain this functionality without writing a single additional line of code.

Start by connecting the switch (UISwitch) to a new action named toggleFlowerDetail by Control-dragging to just below the last @IBOutlet directive in the ViewController.swift file. Make sure that the action is triggered from the event Value Changed, as shown in Figure 9.11.

Image

FIGURE 9.11 Connect the switch using the Value Changed event.

Next, Control-drag from the button (UIButton) to a line under the @IBAction you just defined. When prompted, configure a new action, getFlower, that is triggered from the Touch Up Inside event. Finally, we need to target this new getFlower action from the Value Changed event on the segmented control (UISegmentedControl) so that the user can load a new flower just by touching a color.

Switch to the standard editor and make sure that the document outline is visible (Editor, Show Document Outline). Select the segmented control, and open the Connections Inspector by pressing Option-Command-6 (View, Utilities, Connections Inspector). Drag from the circle beside Value Changed to the View Controller line in the document outline, as demonstrated in Figure 9.12. Release your mouse button and choose getFlower when prompted.

Image

FIGURE 9.12 Connect the Value Changed event of the segmented control to the getFlower method.


Note

Okay, I admit it. In this example, we took a roundabout way of connecting the segmented control to the getFlower method. We could have also Control-dragged from the segmented control onto the IBAction getFlower line in the assistant editor and instantly had our connection.

The problem with the “easy” approach, however, is that you aren’t given the opportunity of choosing which event triggers the action. It just so happens that in this case, Xcode would choose Value Changed for you.


The interface and its connections are finished. The block of code at the top of your ViewController.swift file should look much like this:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var colorChoice: UISegmentedControl!
    @IBOutlet weak var flowerView: UIWebView!
    @IBOutlet weak var flowerDetailView: UIWebView!

    @IBAction func getFlower(sender: AnyObject) {
    }

    @IBAction func toggleFlowerDetail(sender: AnyObject) {
    }

Implementing the Application Logic

Our view controller needs to implement two pieces of functionality via two action methods. The first, toggleFlowerDetail, shows and hides the flowerDetailView web view, depending on whether the switch has been flipped on (show) or off (hide). The second method, getFlower, loads a flower image into the flowerView web view and details on that photograph into the flowerDetailView web view. We start with the easier of the two, toggleFlowerDetail.

Hiding and Showing the Detail Web View

A useful feature of any object that inherits from UIView is that you can easily hide (or show) it within your iOS application interfaces. Because almost everything you see onscreen inherits from this class, this means that you can hide and show labels, buttons, fields, images, and yes, other views. To hide an object, you just set its Boolean variable property hidden to true. So, to hide the flowerDetailView, we write the following:

flowerDetailView.hidden=true

To show it again, we just reverse the process, setting the hidden property to false:

flowerDetailView.hidden=false

To implement the logic for the toggleFlowerDetail method, we need to figure out what value the switch is currently set to. As mentioned earlier in the lesson, we can check the state of a toggle switch through the on variable property: true if the switch is set to on, false if it is off.

Because we don’t have an outlet specifically set aside for the switch, we’ll use the sender variable to access it in our method. When the toggleFlowerDetail action method is called, this variable is set to reference the object that invoked the action (in other words, the switch). Unfortunately, the sender is defined as being of the type AnyObject, so we’ll get an error if we try to access the on variable property because Xcode doesn’t know that it’s a switch. We could just redefine the method so that the incoming parameter is a UISwitch (rather than AnyObject), but why take the easy way out? Instead, we can use a form of typecasting called downcasting to force sender to be recognized as a UISwitch by using the syntax <variable> as! <object>.

In other words, to access sender as an object of type UISwitch, we use the format sender as! UISwitch. The exclamation point forces the downcasting and is required by Xcode when a downcast operation may fail. Because we know that the method is always going to be called by a switch, we can safely force the downcast.

To access the on variable property, wrap the type cast object in parentheses like this:

(sender as! UISwitch).on

So, to check to see whether the switch is on, we can write the following:

if (sender as! UISwitch).on { <switch is on> } else { <switch is off> }

Now, here’s where we can get clever. (You are feeling clever, right?) We want to hide and show the flowerDetailView using a Boolean value and we get a Boolean value from (sender as! UISwitch).on. This maps to two conditions:

Image When (sender as! UISwitch).on is true, the view should not be hidden (flowerDetailView.hidden = false).

Image When (sender as! UISwitch).on is false, the view should be hidden (flowerDetailView.hidden = true).

In other words, the state of the switch is the exact opposite of what we need to assign to the hidden variable property of the view. In Swift, to get the opposite of a Boolean value, we just put an exclamation mark in front (!). So, all we need to do to hide or show flowerDetailView is to set the hidden variable property to !(sender as! UISwitch).on. That’s it. A single line of code.

Implement toggleFlowerDetail in the FlowerWeb method stub that Xcode provided for you. The full method should look a lot like Listing 9.1.

LISTING 9.1 Implementing the toggleFlowerDetail Method


@IBAction func toggleFlowerDetail(sender: AnyObject) {
    flowerDetailView.hidden = !(sender as! UISwitch).on
}


Loading and Displaying the Flower Image and Details

To fetch our flower images, we use a feature provided by the TeachYourselfiOS.info website specifically for this purpose. We follow four steps to interact with the website:

1. We get the chosen color from the segmented control.

2. We generate a random number called a “session ID” so that TeachYourselfiOS.info can track our request.

3. We request the URL https://teachyourselfios.info/?hour=9&color=<color>&session=<sessionID>, where <color> is the chosen color and <session ID> is the random number. This URL returns a flower photo.

4. We request the URL https://teachyourselfios.info/?hour=9&session=<sessionID>&type=detail, where <session ID> is the same random number. This URL returns the details for the previously requested flower photo.


Caution: Gee, Apple, Thanks for Keeping Me Secure!

In iOS 9, Apple has implemented something called App Transport Security (ATS). This sounds like a good thing, yes? It is, and it isn’t. ATS forces your web requests to use https rather than http. This is fine for web services that provide secure access to secure data, but in many cases, the information doesn’t need to be secure, nor does the web service provide encrypted communications over HTTPS. To get around this, you can enter exceptions into your application’s Info.plist file, but there is no way to change the default behavior. For more information on this helpful feature, be sure to search for “App Transport Security” in the iOS documentation.


Let’s go ahead and see what this looks like in code and then discuss details behind the implementation. Add the getFlower implementation, as shown in Listing 9.2.

LISTING 9.2 Adding the getFlower Implementation


 1: @IBAction func getFlower(sender: AnyObject?) {
 2:     var imageURL: NSURL
 3:     var detailURL: NSURL
 4:     var imageURLString: String
 5:     var detailURLString: String
 6:     var color: String
 7:     let sessionID: Int=random()%50000
 8:
 9:     color=colorChoice.titleForSegmentAtIndex(colorChoice.selectedSegmentIndex)!
10:
11:     imageURLString =
12:     "https://teachyourselfios.info/?hour=9&color=(color)&session=(sessionID)"
13:     detailURLString =
14:       "https://teachyourselfios.info/?hour=9&session=(sessionID)&type=detail"
15:
16:     imageURL=NSURL(string: imageURLString)!
17:     detailURL=NSURL(string: detailURLString)!
18:
19:     flowerView.loadRequest(NSURLRequest(URL: imageURL))
20:     flowerDetailView.loadRequest(NSURLRequest(URL: detailURL))
21: }


This is the most complicated code that you’ve written so far, but let’s break it down into the individual pieces, so it’s not difficult to understand.

In line 1, I’ve added a ? after AnyObject because I want to be able to call this method without providing a value for sender. We’ll get back to the reason behind this a bit later.

Lines 2–6 declare the variables that we need to prepare our requests to the website. The first variables, imageURL and detailURL, are instances of NSURL that contain the URLs that are loaded into the flowerView and flowerDetailView web views. To create the NSURL objects, we need two strings, imageURLString and detailURLString, which we format with the special URLs that we presented earlier, including the color and sessionID values.

Line 7 declares a constant sessionID as an integer and assigns it a random number between 0 and 49999. I’ve used the let (insteed of var) keyword to denote that this is a constant rather than a variable—but a variable would work just as well.

In line 9, we retrieve the title of the selected segment in our instance of the segmented control: colorChoice. To do this, we use the object’s instance method titleForSegmentAtIndex along with the object’s selectedSegmentIndex variable property. The result, colorChoice.titleForSegmentAtIndex(colorChoice.selectedSegmentIndex)!, is stored in the string color and is ready to be used in the web request. Notice the exclamation mark at the end of that line? The ! indicates that we’re explicitly unwrapping the value returned by titleForSegmentAtIndex. This is required because the definition of the method indicates it could return a string; or, if a title was never set, it could return nil. Obviously we’ve set titles for everything, so this should be a nonissue for us. However, because titleForSegmentAtIndex was written to return optional strings, we have to acknowledge this fact and explicitly tell Xcode we want to use (unwrap) the value by adding the ! to the end.

Lines 11–14 prepare imageURLString and detailURLString with the URLs that we will be requesting. The color and session ID are substituted into the string definitions using “string interpolation.” That is, we add in the variables we want substituted into the string (color and sessionID) by placing their names in parentheses and adding a backslash to the start: (color) and (sessionID).

Lines 16–17 create the imageURL and detailURL NSURL objects using the NSURL convenience initialization method and the two strings imageURLString and detailURLString. Like the selectedSegmentIndex in line 9, we have to explicitly unwrap the value returned by NSURL by adding an ! to the end, because NSURL documentation states that it may return no value if the string you give it is bad. Because we know we’re giving it a good URL, we can add the ! to the end and move on.

Lines 19–20 use the loadRequest method of the flowerView and flowerDetailView web views to load the NSURLs imageURL and detailURL, respectively. When these lines are executed, the display updates the contents of the two views.


Note

Remember that UIWebView’s loadRequest method doesn’t handle NSURL objects directly; it expects an NSURLRequest object instead. To work around this, we create and return NSURLRequest objects using the NSURLRequest convenient initialization method.


Fixing Up the Interface When the App Loads

Now that the getFlower method is implemented, you can run the application and everything should work—except that when the application starts, the two web views are empty and the detail view is visible, even though the toggle switch is set to off.

To fix this, we can start loading an image as soon as the app is up and running and set flowerDetailView.hidden to true. To do this, update the view controller’s viewDidLoad method as follows in Listing 9.3.

LISTING 9.3 Updating the viewDidLoad Method to Set the Initial Display


override func viewDidLoad() {
    super.viewDidLoad()
    flowerDetailView.hidden=true
    getFlower(nil)
}


As expected, flowerDetailView.hidden=true hides the detail view. Using getFlower(nil), we can call the getFlower method from within our instance of the view control and start the process of loading a flower in the web view. The method getFlower expects a parameter, so we pass it nil, just as we did in the last hour’s lesson. This is also the reason why we added the ? to the getFlower method definition, making the sender’s value optional. If it weren’t optional, we would need to pass it some kind of object; otherwise, the application wouldn’t compile. Because it is optional, sending nil works just fine. Keep in mind that we don’t actually use sender for anything in the getFlower method, so we don’t really care what value it has.


Adding Apple’s Blur

In Hour 8, “Handling Images, Animation, Sliders, and Steppers,” we added a blurred effect to the background of our sample application. This hour’s project also presents an opportunity for blurring. Because this is just a visual effect, and not the focus of the chapter, however, it’s entirely optional.

If you’d like to try adding a blur to the detail view of your version of FlowerWeb, do the following:

1. Using the Object Library, find and drag a copy of the Visual Effect View with Blur to the interface design. This special object blurs the views behind it (you can adjust the type of blur in the Attributes Inspector.)

2. Position the view so that it is the same size as the flowerDetailView, but underneath it—the Editor, Arrange menu can be handy for this. Alternatively, you could place flowerDetailView within the effects view.

3. Edit the detail view so that it is not opaque, and its background color is “clear color” (letting the blur show through).

4. Use the assistant editor to add an outlet for the blurView (blurView) to your code.

5. Add one line of code to ViewController.swift at the bottom of viewDidLoad to hide the blurred view initially:

blurView.hidden = true

6. Add a second line to the end of toggleFlowerDetail that will toggle the blurred view on and off, just like the detail view:

blurView.hidden = !(sender as! UISwitch).on

That’s it. You can play around with this effects view to see what different blurring effects can be created, as well as with the Visual Effects View with Blur and Vibrancy object. Just remember: Too much of a good thing can be (literally) painful on the eyes.

I’ve included this additional code in the FlowerWeb sample.


Building the Application

Test out the final version of the FlowerWeb application by clicking Run in Xcode.

Notice that you can zoom in and out of the web view and use your fingers to scroll around. These are all features that you get without any implementation cost when using the UIWebView class.

Congratulations. Another app under your belt.

Using Scrolling and Stack Views

After working through the projects in the past few hours, iPhone users might begin to notice something: We’re running out of space in our interfaces. Things are starting to get cluttered.

One possible solution, as you learned earlier in this hour, is to use the hidden variable property of UI objects to hide and show them in your applications. Unfortunately, when you’re juggling a few dozen controls, this is pretty impractical. Another approach is to use multiple different views, something that you start learning about in Hour 11.

There is, however, a third way that we can fit more into a single view: by making it scroll. Using an instance of the UIScrollView class, you can add controls and interface elements to a canvas that stretches beyond the physical boundaries of your device’s screen. Unfortunately, although Apple provides access to this object in the IB editor, making it work is a bit less obvious than one might hope.

To keep things nice and neat within a scrolling view, we can throw another object into the mix: the stack view (UIStackView). These, like scroll views, are container objects; they hold other things and are little use on their own. Stack views enable you to add objects to a view and “stack them up” (either vertically or horizontally) without having to worry about detailed placement.

Before closing out this hour, I want to show you how to start using simple scrolling and stack views views in a mini-project.

Implementation Overview

When I say simple, I mean it. This project consists of a scroll view (UIScrollView) with that contains several stack views—all added in the IB editor, as shown in Figure 9.13.

Image

FIGURE 9.13 We’re going to make a view. It will scroll.

To enable scrolling in the view, we need to set a variable property called contentSize, which describes how large the content is that needs to be scrolled. That’s it.

Setting Up the Project

Begin by creating another Single View Application. Name the new project Scroller. For this example, we’re going to be adding the scroll view (UIScrollView) as a subview to the existing view in Main.storyboard. This is a perfectly acceptable approach, but as you get more experienced with the tools, you might want to just replace the default view entirely. Within the scroll view, we’ll add several stack views (UIStackView) to help arrange the content we want to scroll—in this case, icons.

Adding the Icon Resources

Let’s get the icons that we’ll be scrolling added into the project. Open the project group in the project navigator area of Xcode. Click the main Assets.xcassets file to open the project’s image assets. Drag the Icons folder from the Finder into the column on the left inside the asset catalog. A new Icons folder appears within the assets library; time to move on.

Planning the Variables and Connections

We need to do just one thing programmatically in this project, and that’s set a variable property on the scrollView object. To access the scroll view, we’ll connect it, via an outlet, to a new variable property, which we’ll call theScroller.

Designing the Interface

There isn’t much to this project, just a scrolling view, some stack views, and content (a few images). Because you already know how to find objects in the Object Library and add them to a view, this should be trivial. Start by opening the Main.storyboard file for the project and making sure the document outline is visible (Editor, Show Document Outline).

Next, do the same thing you’ve done in previous projects: Set a simulated size for the view controller by selecting the View Controller line in the document outline and then opening the Attributes Inspector (Option-Command-4). Set the Size drop-down to the iOS device screen size that you want (iPhone 4.7-inch for me).

Adding a Scroll View

Using the Object Library (View Utilities, Show Object Library), drag an instance of a scroll view (UIScrollView) into your view. Position the view to fill the scene to the bottom, left, and right edges. Place a label above it that reads Scrolling View (just in case you forget what we’re building). Figure 9.14 shows what your scene should look like at this point.

Image

FIGURE 9.14 Add a scrolling view and label to the scene.


Tip

The text view (UITextView) you used in Hour 7 is a specialized instance of a scrolling view. The same scrolling attributes that you can set for the text view can be applied for the scroll view, so you might want to refer to that earlier hour for more configuration possibilities. Or just press Option-Command-4 to bring up the Attributes Inspector and explore.


Now that your scroll view is added to your design, you need to populate it with something.


Scrolling Through Pages

Scrolling views support the notion of pagination—displaying contents one page at a time rather than showing a single, pageless, stream of text. To turn on pagination, select your scrolling view and check the Paging Enabled property within the Scrolling section of the Attributes Inspector.


Adding Stack Views

The content for our application will be a series of images placed into a horizontal stack view, then several copies of that stack view placed in a vertical stack view. Start by adding four image views into the scrolling area; place them roughly one beside the other and size them to be “icon sized.” You can use the Size Inspector or just eyeball it; we’re not going for precision here. I used a width and height of 50 points in my example.


Tip

Another way to get objects into a scrolling view is to lay them out in your main view however you’d like, select them, and then choose Editor, Embed In, Scroll View from the menu bar. This adds a scrolling view to your interface that contains all the selected objects.


Once the image views are added, use the Attributes Inspector to set the image for each. Choose from one of the icon images that were imported at the start of the project (Icon1, Icon2, Icon3, Icon4, Icon5, or Icon6). Which icon you choose isn’t important. Your design—consisting of just a scroll view, a label, and some icons—should resemble Figure 9.15.

Image

FIGURE 9.15 Add four icons (of your choosing) to the design.

Now, select all four of the image views in the design and click the Stack icon at the bottom of the Interface Builder editor (visible in Figure 9.15). The icons should snap into a horizontal row. If they turn into a vertical column, don’t worry, that’s an easy fix, as you’ll see next.

Make sure that the stack view is selected in the Document Outline; you should see the four image views contained within it. Open the Attributes Inspector (Command-Option-4), and verify that Axis is set to Horizontal. This controls whether it is a horizontal or vertical stack. Next, set the spacing attribute to a visually pleasing number. I’ve used 30. You’ll see the icons space themselves out in the design view, as shown in Figure 9.16.

Image

FIGURE 9.16 Add the 4 icons to a horizontal stack view.

The Alignment and Distribution menus control what happens if the items in the stack view are different sizes or are part of an Auto Layout controlled design; you’ll learn about Auto Layout in Hour 16.

You now have the first row of your icon grid created. The next step is to make copies of the rows and place them in a vertical stack view. Go ahead and copy and paste the horizontal stack view around 10 times.

Once you’re done, select all 10 of the horizontal stack views, and then click the Stack icon in the editor once again. They should immediately stack up in a vertical stack view. Select the vertical stack view and use the Attributes Inspector to set the vertical spacing to around 50 points, as shown in Figure 9.17. If for some reason the stack wasn’t created vertically, you can also use the Axis drop-down to switch it to Vertical.

Image

FIGURE 9.17 The final layout, with one vertical stack view, ten horizontal stack views, and one scrolling view.

Notice that not all the horizontal stacks are visible anymore? When we set the vertical spacing, it pushed some of them down below the visible area of the scroll view. The point of all of this was to make sure that some of the icons are off the screen, meaning we’ll have to scroll to see them. (We’ve also learned about stack views, so that’s a good thing too.)

Now we just need to make the whole thing scroll with a tiny bit of code. Don’t worry, you’ll be done before you even know you’ve started!


Stack Views and the Object Library

If you look, you’ll find the horizontal and vertical stack views living in the Object Library. In this example, we selected objects we wanted added to one of these views, and then used the Stack button in Interface Builder to add them to a stack view. You could also drag a stack view from the Object Library and then drag your objects into that view.



Setting a Freeform Size

When laying out scrolling views (or any view that may hold more content than you can see on the simulated iOS device screen), you may want to switch to the Simulated Size for the scene (or the scene’s view controller) to Freeform. Once in freeform mode, you can select the scene’s main view and set the size to anything you want—making it easy to work with offscreen content.


Creating and Connecting the Outlets and Actions

This project needs only a single outlet and no actions. To create the outlet, switch to the assistant editor and disable the project navigator if you need to make a bit of extra room. Control-drag from the scroll view to the line following the class line in the ViewController.swift file.

When prompted, create a new outlet called theScroller, as shown in Figure 9.18.

Image

FIGURE 9.18 Create the connection to the theScroller outlet.

That finishes up our work in the IB editor; just a teensy bit of implementation remains. Switch back to the standard editor, enable the project navigator, and then select the ViewController.swift file to finish the implementation.

Implementing the Application Logic

For fun, try to run the application as it stands. It compiles and launches, but it doesn’t scroll (at least not correctly). The reason for this is because iOS needs to know the horizontal and vertical sizes of the region it is going to scroll. Until the scrolling view knows that it can scroll, it doesn’t.

Adding Scrolling Behavior

To add scrolling to our scroll view, we need to set the contentSize attribute to a CGSize value. CGSize is just a simple data structure that contains a height and a width, and we can easily make one using the CGSizeMake(<width>,<height>) function.

For example, to tell our scroll view (theScroller) that it can scroll up to 300 points horizontally and 1,000 points vertically, we could enter the following:

theScroller.contentSize=CGSizeMake(300.0,1000.0)

Guess what? That isn’t just what we could do, it’s what we will do. If you’re developing on the iPhone, edit the ViewController.swift file and update the method viewDidLoad shown in Listing 9.4.

LISTING 9.4 Enabling Scrolling in Your Scroll View


override func viewDidLoad() {
    super.viewDidLoad()
    theScroller.contentSize=CGSizeMake(300.0,1000.0)
}


If you are working on the iPad, you need to adjust the size to be a bit larger because the screen is larger. Provide the arguments 900.0 and 2000.0 to the CGSizeMake function, instead of 300.0 and 1000.0.

The single line we added to the method line sets the contentSize and enables the scrolling, ta da!


Where Did You Get the Width and Height Values?

The width we used in this example is the width of the scroll view itself (or smaller). Why? Because we don’t have any reason to scroll horizontally. The height is just the vertical size of the view that would hold all of the icons (if we could see them). In other words, these change depending on the size that the scrolling view must be to fit all your content. Use whatever works best for your application. Feel free to play around; it won’t hurt anything to experiment!



Caution: Wrong Makes Right

Depending on how much attention to pay to developer forums, you’ll find that some who proselytize the notion that Auto Layout (a system you’ll learn about in Hour 16, “Building Responsive User Interfaces”) will automatically calculate the sizes of your scrolling views and will make them scroll automatically. Adding additional code is unnecessary.

Unfortunately, Auto Layout is still rapidly evolving, and many developers have spent sleepless nights trying to make it work for scrolling views. As of iOS 9, it’s still not perfect. If we have to add two or three lines of code to ensure that it works right, no matter what, that seems like the smart thing to do.


Building the Application

The moment of truth has arrived. Does the single line of code make magic? Choose Run from the Xcode toolbar, and then try scrolling around the view you created. Everything should work like a charm.


Tip

Okay, so it’s not technically a single line of code for the entire implementation, but it is a single line that makes the scrolling view work.


Yes, this was a quick-and-dirty project, but there seems to be a lack of information on getting started with UIScrollView and UIStackView objects. So, I thought it was important to run through a short tutorial. I hope this gives you new ideas about what you can do to create more feature-rich iOS interfaces.


Caution: The Warning Signs Are There. Ignore Them

When building this application, you’ll notice a few warnings appearing in Xcode. These are related to the Auto Layout system and don’t affect the functionality of the application. You can revisit this project (if you’d like) after Hour 16 and quickly correct them.


Further Exploration

As well as useful, the segmented control (UISegmentedControl) and switch (UISwitch) classes are pretty easy to get the hang of. The best place to focus your attention for additional exploration is on the feature set provided by the UIWebView and UIScrollView classes.

As described at the start of this hour, UIWebView can handle a large variety of content beyond what might be inferred by the “web” portion of its name. By learning more about NSURL, such as the initFileURLWithPath:isDirectory method, you’ll be able to load files directly from your project resources. You can also take advantage of the web view’s built-in actions, such as goForward and goBack, to add navigation functionality without a single line of code. One might even use a collection of HTML files to create a self-contained website within an application. In short, web views extend the traditional interface of your applications by bringing in HTML markup, JavaScript, and CSS—creating a potent combination.

The UIScrollView class, in contrast, gives us an important capability that is widely used in iOS applications: touch scrolling. We briefly demonstrated this at the end of the hour, but you can enable additional features, such as pinching and zooming, by implementing the UIScrollViewDelegate protocol. We take our first look at building a class that conforms to a protocol in the next hour, so keep this in mind as you get more comfortable with the concepts.

Finally, the UIStackView class can be used for creating orderly user interfaces that size nicely on any device. Coupled with Auto Layout (Hour 16), you can use stack views to create rows and columns of content that resize to fit iPhone and iPad displays without all the complexities of trying to calculate interface sizes yourself.


Apple Tutorials

Segmented Controls, Switches, and Web Views – UICatalog (accessible via the Xcode developer documentation): Mentioned in Hour 8, UICatalog shows nearly all the iOS interface concepts in clearly defined examples.

Scrolling – ScrollViewSuite (accessible via the Xcode developer documentation): The ScrollViewSuite provides examples of just about everything you could ever want to do in a scroll view.


Summary

In this hour, you learned how to use two controls that enable applications to respond to user input beyond just a simple button press or a text field. The switch and segmented control, while limited in the options they can present, give a user a touch-friendly way of making decisions within your applications.

You also explored how to use web views to bring web content directly into your projects and how to tweak it so that it integrates into the overall iOS user experience. This powerful class will quickly become one of your most trusted tools for displaying content.

Because we’ve reached a point in our development where interface layouts are getting a bit cramped, we closed out the hour with a quick introduction to two “container” views: scroll and stack views. You learned how that, despite appearances, you can easily add these unique views (and their associated capabilities) to apps.

Q&A

Q. Can stack views (UIStackView) resize with my windows?

A. Yes! You’ll need the Auto Layout features of Hour 16 to accomplish this, but yes, it’s absolutely possible. You will “pin” the sides of a stack view to the sides of your application view. The stack view will then resize and space its contents out evenly over your view.

Q. You mentioned the UIWebView includes actions. What does that mean, and how do I use them?

A. This means that the object you drag into your view is already capable of responding to actions (such as navigation actions) on its own—no code required. To use these, you connect from the UI event that should trigger the action to your instance of the web view and then choose the appropriate action from the pop-up window that appears.

Workshop

Quiz

1. What common iOS view feature can you add to a project through the Visual Effect view?

a. Blurring

b. Flashing

c. Transparency

d. Voiceover functionality

2. Which operator, when placed at the start of a Boolean value, results in the opposite of that value?

a. ?

b. *

c. &

d. !

3. What type of object does a web view expect as a parameter when loading a remote URL?

a. NSURL

b. NSURLRequest

c. NSRequestURL

d. LoadRequest

4. What variable property can be set to true on a view to make it not visible?

a. invisible

b. noshow

c. nodisplay

d. hidden

5. If we want to use a method and not supply a value to one of its parameters, that parameter must be set as which of the following?

a. Transient

b. Unwrapped

c. Empty

d. Optional

6. If an instance method returns an optional value, we can only use it after doing what?

a. Opening it

b. Unwrapping it

c. Displaying it

d. Querying it

7. This view accepts objects and presents them in a horizontal or vertical column?

a. Freeform view

b. Grid view

c. Stack view

d. Fixed view

8. The selectedSegmentIndex variable property of a segmented control assigns the first segment what value?

a. 0

b. 1

c. –1

d. nil

9. To typecast an object to another type, you use the syntax <myObject> ____ <cast object type>. What keyword is missing in the middle?

a. with

b. from

c. as

d. using

10. A method that quickly creates and returns an object is called what?

a. An initialization method

b. A quick start method

c. A convenience initialization method

d. A swift initialization method

Answers

1. A. Visual effects, such as the frosted glass/blurring effect in iOS, are easily added via the UIVisualEffectView.

2. D. To get the opposite of a Boolean value, simply prefix it with the ! character.

3. B. The NSURLRequest object is needed prior to making a remote web request.

4. D. Set the hidden variable property to true to quickly hide most visual elements in iOS.

5. D. Method parameters must be defined as Optional if you want to invoke them without a value.

6. B. Methods that return an optional value must be unwrapped before use.

7. A. The stack view gives us a container view that organizes content into horizontal or vertical columns.

8. A. The first segment in a segmented control is considered the 0 segment.

9. C. To typecast one object to another, use the keyword as (for example, <myObject> as <another Object type>).

10. C. Methods that quickly create and return a new object are known as convenience initialization methods.

Activities

1. Create your own “mini” web browser by combining a text field, buttons, and a segmented control with a web view. Use the text field for URL entry, buttons for navigation, and hard-code some shortcuts for your favorite sites into the segmented control. To make the best use of space, you may want to overlay the controls on the web view and then add a switch that hides or shows the controls when toggled.

2. Change the FlowerWeb application to take on a more “Apple-y” appearance. Extend the main UIWebView to cover the entire screen, but blur the area behind the main controls.

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

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