Dismissing the Keyboard

Run the application, add and select an item, and touch the text field with the item’s name. When you touch the text field, a keyboard appears onscreen (Figure 12.7), as you saw in your WorldTrotter app in Chapter 6. (If you are using the simulator and the keyboard does not appear, remember that you can press Command-K to toggle the device keyboard.)

Figure 12.7  Keyboard appears when a text field is touched

Keyboard appears when a text field is touched

The appearance of the keyboard in response to a touch is built into the UITextField class as well as UITextView, so you do not have to do anything extra for the keyboard to appear. However, at times you will want to make sure the keyboard behaves as you want it to.

For example, notice that the keyboard covers more than a third of the screen. Right now, it does not obscure anything, but soon you will add more details that extend to the bottom of the screen, and users will want a way to hide the keyboard when it is not needed. In this section, you are going to give the user two ways to dismiss the keyboard: pressing the keyboard’s Return key and tapping anywhere else on the detail view controller’s view. But first, let’s look at the combination of events that make text editing possible.

Event handling basics

When you touch a view, an event is created. This event (known as a touch event) is tied to a specific location in the view controller’s view. That location determines which view in the hierarchy the touch event is delivered to.

For example, when you tap a UIButton within its bounds, it will receive the touch event and respond in button-like fashion – by calling the action method on its target. It is perfectly reasonable to expect that when a view in your application is touched, that view receives a touch event, and it may choose to react to that event or ignore it. However, views in your application can also respond to events without being touched. A good example of this is a shake. If you shake the device with your application running, one of your views on the screen can respond. But which one? Another interesting case is responding to the keyboard. DetailViewController’s view contains three UITextFields. Which one will receive the text when the user types?

For both the shake and keyboard events, there is no event location within your view hierarchy to determine which view will receive the event, so another mechanism must be used. This mechanism is the first responder status. Many views and controls can be a first responder within your view hierarchy – but only one at a time. Think of it as a flag that can be passed among views. Whichever view holds the flag will receive the shake or keyboard event.

Instances of UITextField and UITextView have an uncommon response to touch events. When touched, a text field or a text view becomes the first responder, which in turn triggers the system to put the keyboard onscreen and send the keyboard events to that text field or view. The keyboard and the text field or view have no direct connection, but they work together through the first responder status.

This is a neat way to ensure that the keyboard input is delivered to the correct text field. The concept of a first responder is part of the broader topic of event handling in Cocoa Touch programming that includes the UIResponder class and the responder chain. You can visit Apple’s Using Responders and the Responder Chain to Handle Events for more information.

Dismissing by pressing the Return key

Now let’s get back to allowing users to dismiss the keyboard. If you touch another text field in the application, that text field will become the first responder, and the keyboard will stay onscreen. The keyboard will only give up and go away when no text field (or text view) is the first responder. To dismiss the keyboard, then, you call resignFirstResponder() on the text field that is the first responder.

To have the text field resign in response to the Return key being pressed, you are going to implement the UITextFieldDelegate method textFieldShouldReturn(_:). This method is called whenever the Return key is pressed.

First, in DetailViewController.swift, have DetailViewController conform to the UITextFieldDelegate protocol.

Listing 12.4  Conforming to the UITextFieldDelegate protocol (DetailViewController.swift)

class DetailViewController: UIViewController, UITextFieldDelegate {

Next, implement textFieldShouldReturn(_:) to call resignFirstResponder() on the text field that is passed in.

Listing 12.5  Dismissing the keyboard upon tapping Return (DetailViewController.swift)

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}

Finally, open Main.storyboard and connect the delegate property of each text field to the Detail View Controller (Figure 12.8). (Control-drag from each UITextField to the Detail View Controller and choose delegate.)

Figure 12.8  Connecting the delegate property of a text field

Connecting the delegate property of a text field

Build and run the application. Add an item and drill down to its detail view. Tap a text field and then press the Return key on the keyboard. The keyboard will disappear. To get the keyboard back, tap any text field.

Dismissing by tapping elsewhere

It would be stylish to also dismiss the keyboard if the user taps anywhere else on DetailViewController’s view. To do this, you are going to use a gesture recognizer when the view is tapped, just as you did in the WorldTrotter app. In the action method, you will call resignFirstResponder() on the text field.

Open Main.storyboard and find Tap Gesture Recognizer in the object library. Drag this object onto the background view for the Detail View Controller. You will see a reference to this gesture recognizer in the scene dock.

In the project navigator, Option-click DetailViewController.swift to open it in an additional editor. Control-drag from the tap gesture recognizer in the storyboard to the implementation of DetailViewController.

In the panel that appears, select Action from the Connection menu. Name the action backgroundTapped. For the Type, choose UITapGestureRecognizer (Figure 12.9).

Figure 12.9  Configuring a UITapGestureRecognizer action

Configuring a UITapGestureRecognizer action

Click Connect and the stub for the action method will appear in DetailViewController.swift. Update the method to call endEditing(_:) on the view of DetailViewController.

Listing 12.6  Dismissing the keyboard upon tapping the background view (DetailViewController.swift)

@IBAction func backgroundTapped(_ sender: UITapGestureRecognizer) {
    view.endEditing(true)
}

Calling endEditing(_:) is a convenient way to dismiss the keyboard without having to know (or care) which text field is the first responder. When the view gets this call, it checks whether any text field in its hierarchy is the first responder. If so, then resignFirstResponder() is called on that particular view.

Build and run your application, add an item, and tap it. Tap a text field to show the keyboard. Tap the view outside of a text field, and the keyboard will disappear.

There is one final case where you need to dismiss the keyboard. When the user taps the Back button, viewWillDisappear(_:) is called on the DetailViewController before it is popped off the stack, and the keyboard disappears instantly, with no animation. To dismiss the keyboard more smoothly, update the implementation of viewWillDisappear(_:) in DetailViewController.swift to call endEditing(_:).

Listing 12.7  Dismissing the keyboard when the view controller is going offscreen (DetailViewController.swift)

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    // Clear first responder
    view.endEditing(true)

    // "Save" changes to item
    item.name = nameField.text ?? ""
    item.serialNumber = serialNumberField.text

    if let valueText = valueField.text,
        let value = numberFormatter.number(from: valueText) {
        item.valueInDollars = value.intValue
    } else {
        item.valueInDollars = 0
    }
}
..................Content has been hidden....................

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