Creating an Interactive iOS 17 App

The previous chapter looked at the design patterns we need to learn and use regularly while developing iOS-based apps. In this chapter, we will work through a detailed example intended to demonstrate the ViewController relationship together with the implementation of the Target-Action pattern to create an example interactive iOS app.

Creating the New Project

The purpose of the app we are going to create is to perform unit conversions from Fahrenheit to Centigrade. The first step is creating a new Xcode project to contain our app. Start Xcode and, on the Welcome screen, select Create a new Xcode project. Ensure iOS is selected in the toolbar on the template screen before choosing the App template. Click Next, set the product name to UnitConverter, enter your company identifier, and select your development team if you have one. Before clicking Next, change the Language to Swift and the Interface to Storyboard. On the final screen, choose a location to store the project files and click Create to proceed to the main Xcode project window.

Creating the User Interface

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

Figure 16-1

Display the Library panel by clicking on the toolbar button shown in Figure 16-2 while holding down the Option key and dragging a Text Field object from the library onto the View design area:

Figure 16-2

Resize the object and position it so it appears as outlined in Figure 16-3:

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

Figure 16-3

Within the Attributes Inspector panel (View -> Inspectors -> Attributes), type the words Enter temperature into the Placeholder text field. This text will then appear in light gray 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 adding a Button object that may be pressed to initiate the conversion. To achieve this, drag and drop a Button object from the Library to the View. Next, double-click the button object to change 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 indicates it is centered horizontally within 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 Library panel to the View and positioning 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 relative to the containing view. Finally, 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 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 scenes’ views, including the label, by selecting the Editor -> Canvas -> Bounds Rectangles menu option.

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 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-4:

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

Figure 16-4

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

Figure 16-5

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

Figure 16-6

Building and Running the Sample App

Before we implement the view controller code for our app and then connect it to the user interface we have designed, we should perform a test build and run of the app. Click on the run button in the toolbar (the triangular “play” button) to compile the app and run it in the simulator or a connected iOS device. If you are unhappy with how 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 Swift code to add 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 to calculate the temperature. The calculation result will then be presented to the user via the label object. The Action will be a method 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 Outlets.

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

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

When we created our new project, Xcode anticipated our needs, 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.
    }
}Code language: Swift (swift)

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. However, a much more straightforward 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 Editor -> Assistant menu option. Alternatively, it may also be displayed by selecting the Adjust Editor Options button in the row of Editor toolbar buttons in the top right-hand corner of the main Xcode window and selecting the Assistant menu option, as illustrated in the following figure:

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

Figure 16-7

The editor panel will, by default, appear to the right of the main editing panel in the Xcode window. For example, in Figure 16-8, the panel (marked A) to the immediate right of the Interface Builder panel is the Assistant Editor:

Figure 16-8

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 at the top of the editor panel to select the correct file. The button displaying interlocking circles 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. Drag the resulting line to the area immediately beneath the class declaration line in the Assistant Editor panel, as illustrated in Figure 16-9:

Figure 16-9

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

Figure 16-10

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.

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

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!
.
.
}Code language: Swift (swift)

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 the same as those for an outlet. Once again, select the Main.storyboard file, but this time right-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:

Figure 16-11

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:

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

@IBAction func convertTemp(_ sender: Any) {
}Code language: Swift (swift)

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

@IBAction func convertTemp(_ sender: Any) {
        
    guard let tempString = tempText.text else { return }
    
    if let fahrenheit = Double(tempString) {
        let celsius = (fahrenheit - 32)/1.8
        let resultText = "Celsius \(celsius)"
        resultLabel.text = resultText
    }
}Code language: Swift (swift)

Before proceeding, it is probably a good idea to pause and explain what is happening in the above code. However, those already familiar with Swift may skip the following 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 Any (different type options are available using the Type menu in the connection dialog shown in Figure 16-11 above). This special type 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 method’s behavior 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 method’s body, we use a guard statement to verify that the tempText view contains some text. If it does not, the method simply returns.

Next, dot notation is used 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, optional binding is employed to prevent an attempt to perform the conversion on invalid data.

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

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 to display it to the user.

Building and Running the Finished App

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

Figure 16-12

Hiding the Keyboard

The final step in the app 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 (note when testing on the simulator that the keyboard may not appear unless the I/O -> Keyboard -> Toggle Software Keyboard menu option is selected).

To achieve this, we will begin by implementing the touchesBegan event handler method on the view controller in the ViewController.swift file as follows:

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

override func touchesBegan(_ touches: Set, with event: UIEvent?) {
    tempText.endEditing(true)
}Code language: Swift (swift)

The keyboard will now be hidden when the user touches the background view.

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 with the Type menu set to UITextField as shown in Figure 16-13 and click on the Connect button to establish the connection.

Figure 16-13

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: UITextField) {
    _ = sender.resignFirstResponder()
}Code language: Swift (swift)

In the above method, we call 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 this way indicates to the Swift compiler that we are intentionally ignoring this value.

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

 

You are reading a sample chapter from Building iOS 17 Apps using Xcode Storyboards.

Buy the full book now in eBook or Print format.

The full book contains 96 chapters and 760 pages of in-depth information.

Learn more.

Preview  Buy eBook  Buy Print

 

Summary

In this chapter, we have demonstrated some of the theories covered in previous chapters, in particular, separating the view from the controller, subclassing, and implementing the Target-Action pattern through actions and outlets.

This chapter also provided steps to hide the keyboard when the user touches either the keyboard Return key or the background view.


Categories