Закройте клавиатуру iOS, коснувшись в любом месте с помощью Swift

410

Я искал повсюду для этого, но я не могу найти это. Я знаю, как отклонить использование клавиатуры, Objective-Cно я не знаю, как это сделать, используя Swift? Кто-нибудь знает?

лагуна
источник
9
Как дела в Objective-C? Обычно это преобразование из одного синтаксиса в другой, и редко это вопрос разных методов / соглашений.
Крейг Отис
5
Я не копался в Swift, но у меня сложилось впечатление, что API тот же…
coreyward
Вы можете проверить этот ответ .
Ахмад Ф

Ответы:

1300
override func viewDidLoad() {
    super.viewDidLoad()

    //Looks for single or multiple taps. 
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")

    //Uncomment the line below if you want the tap not not interfere and cancel other interactions.
    //tap.cancelsTouchesInView = false 

    view.addGestureRecognizer(tap)
}

//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {
    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)
}

Вот еще один способ сделать эту задачу, если вы собираетесь использовать эту функцию в нескольких UIViewControllers:

// Put this piece of code anywhere you like
extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false            
        view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard() {
        view.endEditing(true)
    }
}

Теперь в каждом UIViewController, все, что вам нужно сделать, это вызвать эту функцию:

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

Эта функция входит в стандартную функцию моего репо, которая содержит множество полезных расширений Swift, таких как этот, зацените: https://github.com/goktugyil/EZSwiftExtensions

Esqarrouth
источник
19
Начиная с Swift 2 в первом ответе, замените эту строку-> let tap: UITapGestureRecognizer = UITapGestureRecognizer (target: self, action: #selector (MyViewController.dismissKeyboard))
Сэм Беллероз,
2
это нарушает
стремление tableviewcell к контроллеру tableview
11
Это одно из самых полезных расширений, которые я когда-либо встречал! Спасибо! Единственное предупреждение, которое я хотел бы выразить, это то, что это может помешать didSelectRowAtIndexPath.
Клифтон Лабрум
47
Просто обнаружил этот вопрос и реализовал этот метод. То, что «didSelectRow» tableView / UICollectionView не вызывал, буквально сводило меня с ума. Решение: Просто добавьте в ваш добавочный номер : tap.cancelsTouchesInView = false. Это решило это по крайней мере для меня. Надеюсь, это кому-нибудь поможет
Quantm
10
«Проверьте мой репо» - это новый «Слушает мой новый микстейп»: P
Джош
118

Ответ на ваш вопрос о том, как отключить клавиатуру в Xcode 6.1 с помощью Swift ниже:

import UIKit

class ItemViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textFieldItemName: UITextField!

    @IBOutlet var textFieldQt: UITextField!

    @IBOutlet var textFieldMoreInfo: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        textFieldItemName.delegate = self
        textFieldQt.delegate = self
        textFieldMoreInfo.delegate = self
    }

                       ...

    /**
     * Called when 'return' key pressed. return NO to ignore.
     */
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }


   /**
    * Called when the user click on the view (outside the UITextField).
    */
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }

}

( Источник этой информации ).

Король-Мастер
источник
6
Отличный кусок кода, спасибо! touchsBegan был именно тем, что я искал :)
Lukasz Czerwinski
4
Это не совсем работает для меня. Если я коснусь представления контроллера представления, это работает. Если я коснусь элемента управления в представлении, клавиатура не исчезнет.
user3731622
Это лучший ответ, который я когда-либо использовал! Этот ответ должен быть помечен как правильный. Спасибо чувак!
wagng
Это лучшее решение, которое я видел до сих пор. Небольшое примечание: в более новой версии Swift подпись переопределения немного изменилась. Вам нужно добавить _ перед касаниями: переопределить func touchesBegan (_ касания: установить <UITouch>, с событиемEEvent: UIEvent?)
Regis St-Gelais
1
Этот, вероятно, должен быть помечен как правильный. Текущий принятый ответ делает каждую кнопку в представлении не реагирующей на отображение клавиатуры.
Бартек Спица
39

Swift 4 работает

Создайте расширение, как показано ниже, и вызовите его hideKeyboardWhenTappedAround()в вашем контроллере базового представления.

//
//  UIViewController+Extension.swift
//  Project Name
//
//  Created by ABC on 2/3/18.
//  Copyright © 2018 ABC. All rights reserved.
//

import UIKit

extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tapGesture = UITapGestureRecognizer(target: self, 
                         action: #selector(hideKeyboard))
        view.addGestureRecognizer(tapGesture)
    }

    @objc func hideKeyboard() {
        view.endEditing(true)
    }
}

Наиболее важная вещь для вызова в вашем контроллере базового представления, так что нет необходимости вызывать все время во всех контроллерах представления.

Фахим Паркар
источник
36

Вы можете позвонить

resignFirstResponder()

на любом экземпляре UIResponder, таком как UITextField. Если вы вызываете его в представлении, которое в настоящее время вызывает отображение клавиатуры, клавиатура будет отклонена.

Тире
источник
5
В ситуации, когда вы точно не знаете первого респондента, resignFirstResponder () может привести к куче проблем. Ответ Esq ниже (с использованием view.doneEditing ()) гораздо более уместен
shiser
1
Всякий раз, когда я использую resignFirstResponder в моем textField, приложение вылетает. Я перепробовал все, что мог придумать, и искал в Интернете исправления. Ничто не помогает мне. Вы случайно не знаете, почему это происходит?
AugustoQ,
1
Как сказал Шизер, это не лучшее решение. плюс это не работает во всех ситуациях.
Аликс
21
//Simple exercise to demonstrate, assuming the view controller has a //Textfield, Button and a Label. And that the label should display the //userinputs when button clicked. And if you want the keyboard to disappear //when clicken anywhere on the screen + upon clicking Return key in the //keyboard. Dont forget to add "UITextFieldDelegate" and 
//"self.userInput.delegate = self" as below

import UIKit

class ViewController: UIViewController,UITextFieldDelegate {

    @IBOutlet weak var userInput: UITextField!
    @IBAction func transferBtn(sender: AnyObject) {
                display.text = userInput.text

    }
    @IBOutlet weak var display: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

//This is important for the textFieldShouldReturn function, conforming to textfieldDelegate and setting it to self
        self.userInput.delegate = self
    }

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

//This is for the keyboard to GO AWAYY !! when user clicks anywhere on the view
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }


//This is for the keyboard to GO AWAYY !! when user clicks "Return" key  on the keyboard

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

}
Naishta
источник
штрихи Беган помог мне закончить редактирование текстового поля и текстового обзора. Спасибо
Санджу
Это то, что я использую, просто. Удалите также несвязанные коды, чтобы сосредоточиться на решении.
Джон Доу
19

для Swift 3 это очень просто

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

если вы хотите скрыть клавиатуру при нажатии клавиши RETURN

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

но во втором случае вам также нужно будет передать делегат из всех textFields в ViewController в Main.Storyboard

Ербол
источник
Я получаю unrecognized selector sent to instanceс этим кодом.
Haring10
11

Swift 3: самый простой способ отклонить клавиатуру:

  //Dismiss keyboard method
    func keyboardDismiss() {
        textField.resignFirstResponder()
    }

    //ADD Gesture Recignizer to Dismiss keyboard then view tapped
    @IBAction func viewTapped(_ sender: AnyObject) {
        keyboardDismiss()
    }

    //Dismiss keyboard using Return Key (Done) Button
    //Do not forgot to add protocol UITextFieldDelegate 
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        keyboardDismiss()

        return true
    }
NikaE
источник
1
Я вполне уверен, что вызов view.endEditing (true) проще, поскольку он не требует хранения переменной или предполагает, что у вас есть только одно текстовое поле.
Гленн Хаус
10

Даш ответ правильный и предпочтительный. Более «выжженная земля» - это колл view.endEditing(true). Это вызывает viewи все его представления resignFirstResponder. Если у вас нет ссылки на представление, которое вы хотели бы отклонить, это хакерское, но эффективное решение.

Обратите внимание, что лично я думаю, что у вас должна быть ссылка на мнение, которое вы хотели бы оставить в отставке первым ответчиком. .endEditing(force: Bool)варварский подход; пожалуйста, не используйте его.

modocache
источник
10

swift 5 достаточно двух строк Добавьте в свою viewDidLoadработу.

 let tapGesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
 view.addGestureRecognizer(tapGesture)

Если ваш жест касания заблокировал некоторые другие касания, добавьте эту строку:

tapGesture.cancelsTouchesInView = false
Уильям Ху
источник
Очень простое и элегантное решение :), ответ должен быть здесь.
Джозеф Астрахань
9

В раскадровке:

  1. выберите TableView
  2. с правой стороны выберите инспектор атрибутов
  3. в разделе клавиатуры - выберите нужный режим отклонения
zevij
источник
не могу найти этот предмет, где он находится и как он выглядит? Я в атрибуте инспектора textField
Итан Паркер
Вам нужно смотреть на TableView, а не на TextField
zevij
9

Свифт 3:

Расширение в Selectorкачестве параметра, чтобы иметь возможность выполнять дополнительные действия в функции dismiss и cancelsTouchesInViewпредотвращать искажения при касании других элементов представления.

extension UIViewController {
    func hideKeyboardOnTap(_ selector: Selector) {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: selector)
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }
}

Применение:

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardOnTap(#selector(self.dismissKeyboard))
}

func dismissKeyboard() {
    view.endEditing(true)
    // do aditional stuff
}
Дэвид Сик
источник
9

Используйте IQKeyboardmanager , который поможет вам легко решить .....

/////////////////////////////////////////

! [как отключить клавиатуру ..] [1]

import UIKit

class ViewController: UIViewController,UITextFieldDelegate {

   @IBOutlet weak var username: UITextField!
   @IBOutlet weak var password: UITextField!

   override func viewDidLoad() {
      super.viewDidLoad() 
      username.delegate = self
      password.delegate = self
      // 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.
   }

   func textFieldShouldReturn(textField: UITextField!) -> Bool // called when   'return' key pressed. return NO to ignore.
   {
      textField.resignFirstResponder()
      return true;
   }

   override func touchesBegan(_: Set<UITouch>, with: UIEvent?) {
     username.resignFirstResponder()
     password.resignFirstResponder()
     self.view.endEditing(true)
  }
}
Hardik Bar
источник
8

Я нашел лучшее решение, включающее принятый ответ от @Esqarrouth, с некоторыми корректировками:

extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboardView")
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }

    func dismissKeyboardView() {
        view.endEditing(true)
    }
}

Линия tap.cancelsTouchesInView = falseбыла критической: она гарантирует, чтоUITapGestureRecognizer другие элементы не будут препятствовать взаимодействию с пользователем.

Метод dismissKeyboard()был изменен на чуть менее элегантный dismissKeyboardView(). Это потому, что в довольно старой кодовой базе моего проекта было много раз, когдаdismissKeyboard() он уже использовался (я думаю, что это не редкость), вызывая проблемы компилятора.

Затем, как указано выше, это поведение можно включить в отдельных контроллерах представления:

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround() 
}
Люк Харрис
источник
7

Если вы используете представление прокрутки, это может быть намного проще.

Просто выберите Dismiss interactivelyв раскадровке.

Джи Ван
источник
7

В Swift 4 добавьте @objc:

В viewDidLoad:

let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard))
view.addGestureRecognizer(tap)

Функция:

@objc func dismissKeyboard() {
  view.endEditing(true)
}
user3856297
источник
7

Добавьте это расширение к вашему ViewController:

  extension UIViewController {
// Ends editing view when touches to view 
  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    self.view.endEditing(true)
  }
}
Джарвис Мститель
источник
6

Чтобы расширить ответ Эскарута , я всегда использую следующее, чтобы отклонить клавиатуру, особенно если класс, из которого я отклоняю клавиатуру , не имеет viewсвойства и / или не является подклассомUIView .

UIApplication.shared.keyWindow?.endEditing(true)

И, для удобства, следующее расширение UIApplcationкласса:

extension UIApplication {

    /// Dismisses the keyboard from the key window of the
    /// shared application instance.
    ///
    /// - Parameters:
    ///     - force: specify `true` to force first responder to resign.
    open class func endEditing(_ force: Bool = false) {
        shared.endEditing(force)
    }

    /// Dismisses the keyboard from the key window of this 
    /// application instance.
    ///
    /// - Parameters:
    ///     - force: specify `true` to force first responder to resign.
    open func endEditing(_ force: Bool = false) {
        keyWindow?.endEditing(force)
    }

}
NoodleOfDeath
источник
5
  import UIKit

  class ItemViewController: UIViewController, UITextFieldDelegate {

  @IBOutlet weak var nameTextField: UITextField!

    override func viewDidLoad() {
           super.viewDidLoad()
           self.nameTextField.delegate = self
     }

    // Called when 'return' key pressed. return NO to ignore.

    func textFieldShouldReturn(textField: UITextField) -> Bool {

            textField.resignFirstResponder()
             return true
     }

 // Called when the user click on the view (outside the UITextField).

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)    {
      self.view.endEditing(true)
  }
}
Прашант Чаудхари
источник
5

Как начинающий программист, это может сбивать с толку, когда люди производят более квалифицированные и ненужные ответы ... Вам не нужно делать никаких сложных вещей, показанных выше! ...

Вот самый простой вариант ... В случае, если ваша клавиатура появляется в ответ на текстовое поле - внутри вашей функции сенсорного экрана просто добавьте функцию resignFirstResponder . Как показано ниже - клавиатура закроется, потому что Первый Ответчик освобожден (выход из цепочки Ответчика) ...

override func touchesBegan(_: Set<UITouch>, with: UIEvent?){
    MyTextField.resignFirstResponder()
}
Красное небо
источник
5

Я использую IQKeyBoardManagerSwift для клавиатуры. Это простой в использовании. просто добавьте модуль 'IQKeyboardManagerSwift'

Импортируйте IQKeyboardManagerSwift и напишите код didFinishLaunchingWithOptionsв AppDelegate.

///add this line 
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
IQKeyboardManager.shared.enable = true
Суквиндер Сингх
источник
4

Этот один вкладыш отказывается от клавиатуры от всех (любых) UITextField в UIView

self.view.endEditing(true)
Codetard
источник
4

Всего одна строка кода в viewDidLoad()методе:

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
Артем
источник
4

В Swift вы можете использовать

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

}
Бернард Райосо
источник
3

Для Swift3

Зарегистрируйте распознаватель событий в viewDidLoad

let tap = UITapGestureRecognizer(target: self, action: #selector(hideKeyBoard))

тогда нам нужно добавить жест в представление в том же viewDidLoad.

self.view.addGestureRecognizer(tap)

Затем нам нужно инициализировать зарегистрированный метод

func hideKeyBoard(sender: UITapGestureRecognizer? = nil){
    view.endEditing(true)
}
Санду
источник
1
Спасибо за полный ответ и с примечаниями. Это единственное решение, которое сработало для меня.
Зеешан
3

Публикация в качестве нового ответа, так как мое редактирование ответа @ King-Wizard было отклонено.

Сделайте ваш класс делегатом UITextField и переопределите touchSegan.

Swift 4

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        textField.delegate = self
    }

    //Called when 'return' key is pressed. Return false to keep the keyboard visible.
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        return true
    }

    // Called when the user clicks on the view (outside of UITextField).
    override func touchesBegan(touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

}
Виктор Сеч
источник
2

Вы также можете добавить распознаватель жестов касания, чтобы оставить клавиатуру. : D

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

    let recognizer = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    backgroundView.addGestureRecognizer(recognizer)
}
    func handleTap(recognizer: UITapGestureRecognizer) {
    textField.resignFirstResponder()
    textFieldtwo.resignFirstResponder()
    textFieldthree.resignFirstResponder()

    println("tappped")
}
Codetard
источник
2

Другая возможность - просто добавить большую кнопку без содержимого, которое находится под всеми представлениями, к которым вам, возможно, нужно прикоснуться. Дайте ему действие с именем:

@IBAction func dismissKeyboardButton(sender: AnyObject) {
    view.endEditing(true)
}

Проблема с распознавателем жестов была для меня в том, что он также улавливал все касания, которые я хотел получить с помощью tableViewCells.

Тимм Кент
источник
2

Если у вас есть другие виды, которые должны получить сенсорный, вы должны установить cancelsTouchesInView = false

Нравится:

let elsewhereTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    elsewhereTap.cancelsTouchesInView = false
    self.view.addGestureRecognizer(elsewhereTap)
ph1lb4
источник
2
override func viewDidLoad() {
        super.viewDidLoad()

self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap)))

}

func tap(sender: UITapGestureRecognizer){
        print("tapped")
        view.endEditing(true)
}

Попробуйте это, это работает

Рампрасат Сельвам
источник
1

Когда в представлении есть более одного текстового поля

Для того, чтобы следовать @ рекомендации modocache - х избежать вызоваview.endEditing() , вы можете отслеживать текстовое поле, которое стало первым респондентом, но это грязно и подвержено ошибкам.

Альтернативой является вызов resignFirstResponder() всех текстовых полей в viewcontroller . Вот пример создания коллекции всех текстовых полей (которые в любом случае были необходимы для кода проверки в любом случае):

@IBOutlet weak var firstName: UITextField!
@IBOutlet weak var lastName: UITextField!
@IBOutlet weak var email: UITextField!

var allTextFields: Array<UITextField>!  // Forced unwrapping so it must be initialized in viewDidLoad
override func viewDidLoad()
{
    super.viewDidLoad()
    self.allTextFields = [self.firstName, self.lastName, self.email]
}

Имея доступную коллекцию, вы легко можете пройтись по всем из них:

private func dismissKeyboard()
{
    for textField in allTextFields
    {
        textField.resignFirstResponder()
    }
}

Так что теперь вы можете вызвать dismissKeyboard()свой распознаватель жестов (или там, где вам удобно). Недостатком является то, что вы должны поддерживать список UITextFields при добавлении или удалении полей.

Комментарии приветствуются. Если есть проблема с вызовом resignFirstResponder()элементов управления, которые не являются первыми респондентами, или если есть простой и гарантированный не ошибочный способ отследить текущего первого респондента, я хотел бы услышать об этом!

камень
источник