Creating an Interactive iOS 10 App

From Techotopia
Revision as of 04:21, 10 November 2016 by Neil (Talk | contribs) (Creating the User Interface)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

PreviousTable of ContentsNext
Understanding Error Handling in SwiftAn Introduction to Auto Layout in iOS 10


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


In the previous chapter we looked at the design patterns that we will need to learn and use regularly in the course of developing iOS 10 based applications. In this chapter we will work through a detailed example intended to demonstrate the View-Controller relationship together with the implementation of the Target-Action pattern to create an example interactive iOS 10 application.


Contents


Creating the New Project

The purpose of the application we are going to create is to perform unit conversions from Fahrenheit to Centigrade. Obviously the first step is to create a new Xcode project to contain our application. Start Xcode and, on the Welcome screen, select Create a new Xcode project. On the template screen make sure iOS is selected in the toolbar before choosing the Single View Application template. Click Next, set the product name to UnitConverter, enter your company identifier and make sure that the Devices menu is set to Universal so that the user interface will be suitable for deployment on all iPhone and iPad screen sizes. Before clicking Next, change the Language menu to Swift. On the final screen, choose a location in which to store the project files and click on Create to proceed to the main Xcode project window.

Creating the User Interface

Before we begin developing the logic for our interactive application we are going to start by designing the user interface. When we created the new project, Xcode generated a storyboard file for us and named it Main.storyboard. It is within this file that we will create our user interface, so select this file from the project navigator in the left-hand panel to load it into Interface Builder.


A new Xcode project

Figure 16-1


From the Object Library panel, drag a Text Field object onto the View design area. Resize the object and position it so that it appears as outlined in Figure 16-2.

A simple example user interface layout

Figure 16-2


Within the Attributes Inspector panel (View -> Utilities -> Show Attributes Inspector), type the words Enter temperature into the Placeholder text field. This text will then appear in a light gray color in the text field as a visual cue to the user. Since only numbers and decimal points will be required to be input for the temperature, locate the Keyboard Type property in the Attributes Inspector panel and change the setting to Numbers and Punctuation.

Now that we have created the text field into which the user will enter a temperature value, the next step is to add a Button object which may be pressed to initiate the conversion. To achieve this, drag and drop a Button object from the Object Library to the View. Double-click the button object so that it changes to text edit mode and type the word Convert onto the button. Finally, select the button and drag it beneath the text field until the blue dotted line appears indicating it is centered horizontally in relation to the containing view before releasing the mouse button.

The last user interface object we need to add is the label where the result of the conversion will be displayed. Add this by dragging a Label object from the Object Library panel to the View and position it beneath the button. Stretch the width of the label so that it is approximately two thirds of the overall width of the view and reposition it using the blue guidelines to ensure it is centered in relation to the containing view. Modify the Alignment attribute for the label object so that the text is centered.

Double-click on the label to highlight the text and press the backspace key to clear it (we will set the text from within a method of our View Controller class when the conversion calculation has been performed). Though the label is now no longer visible when it is not selected, it is still present in the view. If you click where it is located it will be highlighted with the resize dots visible. It is also possible to view the layout outlines of all the views in the scene, including the label, by selecting the Editor -> Canvas -> Show Bounds Rectangles menu option.

In order for the user interface design layout to adapt to the many different device orientations and iPad and iPhone screen sizes it will be necessary to add some Auto Layout constraints to the views in the storyboard. Auto Layout will be covered in detail in subsequent chapters, but for the purposes of this example, we will request that Interface Builder add what it considers to be the appropriate constraints for this layout. In the lower right-hand corner of the Interface Builder panel is a toolbar. Click on the background view of the current scene followed by the Resolve Auto Layout Issues button as highlighted in Figure 16-3:


The Xcode 8 "Resolve Auto Layout Issues" button

Figure 16-3

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

From the menu, select the Reset to Suggested Constraints option listed under All Views in View Controller:


The Interface Builder Resolve Auto Layout issues menu

Figure 16-4


At this point the user interface design phase of our project is complete and the view should appear as illustrated in Figure 16 5. We now are ready to try out a test build and run.


Example iOS user interface built using Interface Builder in Xcode 8

Figure 16-5


Building and Running the Sample Application

Before we move on to implementing the view controller code for our application and then connecting it to the user interface we have designed we should first perform a test build and run of the application so far. Click on the run button located in the toolbar (the triangular “play” button) to compile the application and run it in the simulator or a connected iOS device. If you are not happy with the way your interface looks feel free to reload it into Interface Builder and make improvements. Assuming the user interface appears to your satisfaction we are ready to start writing some Swift code to add some logic to our controller.

Adding Actions and Outlets

When the user enters a temperature value into the text field and touches the convert button we need to trigger an action which will perform a calculation to convert the temperature. The result of that calculation will then be presented to the user via the label object. The Action will be in the form of a method which we will declare and implement in our View Controller class. Access to the text field and label objects from the view controller method will be implemented through the use of Outlets.

Before we begin, now is a good time to highlight an example of the use of subclassing as previously described in The iOS 10-Application and Development Architecture, the UIKit Framework contains a class called UIViewController which provides the basic foundation for adding view controllers to an application. In order to create a functional application, however, we inevitably need to add functionality specific to our application to this generic view controller class. This is achieved by subclassing the UIViewController class and extending it with the additional functionality we need.

When we created our new project, Xcode anticipated our needs and automatically created a subclass of UIViewController and named it ViewController. In so doing, Xcode also created a source code file named ViewController.swift.

Selecting the ViewController.swift file in the Xcode project navigator panel will display the contents of the file in the editing pane:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

As we can see from the above code, a new class called ViewController has been created that is a subclass of the UIViewController class belonging to the UIKit framework. The next step is to extend the subclass to include the two outlets and our action method. This could be achieved by manually declaring the outlets and actions within the ViewController.swift file. A much easier approach is to use the Xcode Assistant Editor to do this for us.

With the Main.storyboard file selected, display the Assistant Editor by selecting the View -> Assistant Editor -> Show Assistant Editor menu option. Alternatively, it may also be displayed by selecting the center button (the one containing an image of interlocking circles) of the row of Editor toolbar buttons in the top right-hand corner of the main Xcode window as illustrated in the following figure:


The Xcode 8 Assistant Editor toolbar button

Figure 16-6

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

In the event that multiple Assistant Editor panels are required, additional tiles may be added using the View -> Assistant Editor -> Add Assistant Editor menu option.

By default, the editor panel will appear to the right of the main editing panel in the Xcode window. For example, in Figure 16 7 the panel to the immediate right of the Interface Builder panel is the Assistant Editor:


The Xcode 8 Assistant Editor panel

Figure 16-7


By default, the Assistant Editor will be in Automatic mode, whereby it automatically attempts to display the correct source file based on the currently selected item in Interface Builder. If the correct file is not displayed, use the toolbar along the top of the editor panel to select the correct file. The small instance of the Assistant Editor icon in this toolbar can be used to switch to Manual mode allowing the file to be selected from a pull-right menu containing all the source files in the project.

Make sure that the ViewController.swift file is displayed in the Assistant Editor and establish an outlet for the Text Field object by Ctrl-clicking on the Text Field object in the view and dragging the resulting line to the area immediately beneath the class declaration line in the Assistant Editor panel as illustrated in Figure 16-8:


Establishing an outlet connection in Xcode 8

Figure 16-8


Upon releasing the line, the configuration panel illustrated in Figure 16-9 will appear requesting details about the outlet to be defined.


Establishing an outlet connection in Xcode 8

Figure 16-9


Since this is an outlet, the Connection menu should be left as Outlet. The type and storage values are also correct for this type of outlet. The only task that remains is to enter a name for the outlet, so in the Name field enter tempText before clicking on the Connect button.

Once the connection has been established, select the ViewController.swift file and note that the outlet property has been declared for us by the assistant:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tempText: UITextField!
.
.
.
}

Repeat the above steps to establish an outlet for the Label object named resultLabel.

Next we need to establish the action that will be called when the user touches the Convert button in our user interface. The steps to declare an action using the Assistant Editor are essentially the same as those for an outlet. Once again, select the Main.storyboard file, but this time Ctrl-click on the button object. Drag the resulting line to the area beneath the existing viewDidLoad method in the Assistant Editor panel before releasing it. The connection box will once again appear. Since we are creating an action rather than an outlet, change the Connection menu to Action. Name the action convertTemp and make sure the Event type is set to Touch Up Inside:


Establishing an action connection in Xcode 8

Figure 16-10


Click on the Connect button to create the action.

Close the Assistant Editor panel, select the ViewController.swift file and note that a stub method for the action has now been declared for us by the assistant:

@IBAction func convertTemp(_ sender: AnyObject) {
}

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

All that remains is to write the Swift code in the action method to perform the conversion:

@IBAction func convertTemp(_ sender: AnyObject) {
    
    if let fahrenheit = Double(tempText.text!) {
        let celsius = (fahrenheit - 32)/1.8
        let resultText = "Celsius \(celsius)"
        resultLabel.text = resultText
    }
}

Before we proceed it is probably a good idea to pause and explain what is happening in the above code. Those already familiar with Swift, however, may skip the next few paragraphs.

In this file we are implementing the convertTemp method, a template for which was created for us by the Assistant Editor. This method takes as a single argument a reference to the sender. The sender is the object that triggered the call to the method (in this case our Button object). The sender is declared as being of type AnyObject. This is a special type which can be used to represent any type of class. While we won’t be using this object in the current example, this can be used to create a general purpose method in which the behavior of the method changes depending on how (i.e. via which object) it was called. We could, for example, create two buttons labeled Convert to Fahrenheit and Convert to Celsius respectively, each of which calls the same convertTemp method. The method would then access the sender object to identify which button triggered the event and perform the corresponding type of unit conversion.

Within the body of the method we use dot notation to access the text property (which holds the text displayed in the text field) of the UITextField object to access the text in the field. This property is itself an object of type String. This string is converted to be of type Double and assigned to a new constant named fahrenheit. Since it is possible that the user has not entered a valid number into the field the use of optional binding is employed to prevent an attempt to perform the conversion on invalid data.

Having extracted the text entered by the user and converted it to a number, we then perform the conversion to Celsius and store the result in another constant named celsius. Next, we create a new string object and initialize it with text comprising the word Celsius and the result of our conversion. In doing so, we declare a constant named resultText.

Finally, we use dot notation to assign the new string to the text property of our UILabel object so that it is displayed to the user.

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Building and Running the Finished Application

From within the Xcode project window click on the run button located in the Xcode toolbar (the triangular “play” style button) to compile the application and run it in the simulator or a connected iOS device. Once the application is running, click inside the text field and enter a Fahrenheit temperature. Next, click on the Convert button to display the equivalent temperature in Celsius. Assuming all went to plan your application should appear as outlined in the following figure:


The iOS example Swift app running

Figure 16-11

Hiding the Keyboard

The final step in the application implementation is to add a mechanism for hiding the keyboard. Ideally, the keyboard should withdraw from view when the user touches the background view or taps the return key on the keyboard. To achieve this, we will begin by implementing the touchesBegan event handler method on the view controller in the ViewController.swift file as follows:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    tempText.endEditing(true)
}

When the background view is touched by the user, the keyboard will now be hidden.

The next step is to hide the keyboard when the return key is tapped. To do this, display the Assistant Editor and Ctrl-click and drag from the Text Field to a position beneath the viewDidLoad method within the ViewController.swift file. On releasing the line, change the settings in the connection dialog to establish an Action connection named textFieldReturn for the Did End on Exit event as shown in Figure 16-12 and click on the Connect button to establish the connection.

Setting up an action to hide the keyboard in iOS

Figure 16-12

Select the ViewController.swift file in the project navigator, locate and edit the textFieldReturn stub method so that it now reads as follows:

@IBAction func textFieldReturn(_ sender: AnyObject) {
    _ = sender.resignFirstResponder()
}

In the above method we are making a call to the resignFirstResponder method of the object that triggered the event. The first responder is the object with which the user is currently interacting (in this instance, the virtual keyboard displayed on the device screen). Note that the result of the method call is assigned to a value represented by the underscore character (_). The resignFirstResponder() method returns a Boolean value indicating whether or not the resign request was successful. Assigning the result in this way indicates to the Swift compiler that we are intentionally ignoring this value.

Save the code and then build and run the application. When the application starts up, select the text field so that the keyboard appears. Touching any area of the background or tapping the return key should cause the keyboard to disappear.

Summary

In this chapter we have put into practice some of the theory covered in previous chapters, in particular the separation of the view from the controller, the use of subclassing and the implementation of the Target-Action pattern through the use of actions and outlets.

This chapter also provided steps on how to hide the keyboard when either the keyboard Return key or the background view are touched by the user.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
Understanding Error Handling in SwiftAn Introduction to Auto Layout in iOS 10