Avatar ·

Как скрыть клавиатуру на iOS при касании в любом месте экрана (Swift)

Всем привет! Я новичок в iOS-разработке на Swift и столкнулся с типичной проблемой: когда пользователь вводит текст в UITextField, клавиатура появляется, но чтобы её убрать, нужно нажать кнопку "Return" или "Done". Многие пользователи ожидают, что при касании в любом месте экрана (например, на фоне или на другом элементе) клавиатура должна автоматически скрываться. Я пробовал использовать метод `resignFirstResponder()` на текстовом поле, но не понимаю, как связать его с жестом касания по всему view. Вот пример моего кода: ```swift import UIKit class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() // Хочу, чтобы при нажатии на фон клавиатура убиралась } } ``` Подскажите, пожалуйста, как правильно реализовать скрытие клавиатуры при касании в любом месте экрана? Нужно ли добавлять UITapGestureRecognizer, и если да, то как его настроить? Также интересует, как обработать случай, когда на экране несколько текстовых полей. Заранее спасибо! <<>>

Реализация скрытия клавиатуры через UITapGestureRecognizer

Да, вы абсолютно правы — стандартный способ решения этой задачи — добавить UITapGestureRecognizer на основное view контроллера. Когда пользователь касается экрана, распознаватель жестов срабатывает, и мы вызываем метод view.endEditing(true), который заставляет все активные текстовые поля (или другие элементы ввода) сбросить статус "first responder" и скрыть клавиатуру.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var textField2: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 1. Создаем распознаватель жестов
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
        
        // 2. Важно: не отключаем взаимодействие с другими элементами (кнопки, таблицы)
        tapGesture.cancelsTouchesInView = false
        
        // 3. Добавляем на главное view
        view.addGestureRecognizer(tapGesture)
    }
    
    @objc func hideKeyboard() {
        // 4. Скрывает клавиатуру для всех текстовых полей в текущем view
        view.endEditing(true)
    }
}

Почему это работает?

  • view.endEditing(true) — рекурсивно проходит по всем сабвью и вызывает resignFirstResponder() для активного элемента. Это удобно, когда на экране несколько текстовых полей.
  • cancelsTouchesInView = false — гарантирует, что жест не "перехватит" тапы у других элементов (например, кнопок или таблиц). Если этого не сделать, кнопки перестанут реагировать на нажатия.

Альтернативный вариант: метод touchesBegan

Если вы не хотите использовать распознаватель жестов, можно переопределить метод touchesBegan в контроллере:

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

Этот подход проще, но у него есть недостаток: он не сработает, если касание происходит на элементе, который переопределяет touchesBegan (например, на UIScrollView или UITableView). Поэтому UITapGestureRecognizer — более надёжный и гибкий вариант.

Дополнительные советы

  • Проверка активного поля: Если нужно выполнить дополнительные действия перед скрытием (например, валидацию), можно получить ссылку на текущий first responder через UIResponder.currentFirstResponder() (но это уже отдельная тема).
  • Клавиатура с UIScrollView: Если ваш интерфейс использует UIScrollView или UITableView, добавьте распознаватель на self.view, а не на scroll view, чтобы избежать конфликтов с прокруткой.
  • Анимация: endEditing(true) скрывает клавиатуру с анимацией по умолчанию — дополнительно ничего настраивать не нужно.

Таким образом, вы получаете простое и универсальное решение, которое работает для любого количества текстовых полей и не ломает стандартное поведение UI.

<<>>

Использование расширения UIViewController

Если вам нужно повторно использовать этот функционал во многих контроллерах, создайте расширение для UIViewController:

extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }
    
    @objc func dismissKeyboard() {
        view.endEditing(true)
    }
}

Теперь в любом контроллере достаточно вызвать hideKeyboardWhenTappedAround() в viewDidLoad():

override func viewDidLoad() {
    super.viewDidLoad()
    hideKeyboardWhenTappedAround()
}

Важный нюанс с модальными контроллерами

Если ваш контроллер отображается модально (например, present), убедитесь, что распознаватель жестов добавлен именно на его view, а не на родительский. В противном случае клавиатура может не скрываться при касании внутри модального окна.

Этот подход особенно удобен в больших проектах, где много экранов с формами ввода — он избавляет от дублирования кода и делает решение централизованным.