Feche o teclado do iOS tocando em qualquer lugar usando o Swift


409

Eu tenho procurado por tudo isso, mas não consigo encontrá-lo. Eu sei como descartar o teclado usando, Objective-Cmas não tenho idéia de como fazer isso usando Swift? Alguém sabe?


9
Como você está fazendo isso no Objective-C? Normalmente, é uma conversão de uma sintaxe para outra e raramente é uma questão de diferentes métodos / convenções.
Craig Otis

5
Eu não tenho cavado Swift, mas eu estava sob a impressão de que a API é a mesma ...
coreyward

Você pode querer verificar esta resposta .
Ahmad F

Respostas:


1299
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)
}

Aqui está outra maneira de executar esta tarefa se você usar esta funcionalidade em vários 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)
    }
}

Agora em todos UIViewController, tudo o que você precisa fazer é chamar esta função:

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

Esta função está incluída como uma função padrão no meu repositório, que contém muitas Extensões Swift úteis como esta, confira: https://github.com/goktugyil/EZSwiftExtensions


19
Desde Swift 2 na primeira resposta, substituir este line-> vamos torneira: UITapGestureRecognizer = UITapGestureRecognizer (meta: auto, ação: #selector (MyViewController.dismissKeyboard))
Sam Bellerose

2
ele quebra segue de tableviewcell em um tableviewcontroller
Utku Dalmaz

11
Esta é uma das extensões mais úteis que já encontrei! Obrigado! A única cautela que gostaria de estender é que isso pode interferir didSelectRowAtIndexPath.
Clifton Labrum

47
Acabei de descobrir esta questão e implementou esse método. Aquela coisa com "didSelectRow" de tableView / UICollectionView que não estava chamando literalmente me deixou maluca. A solução é: Basta adicionar este a sua extensão: tap.cancelsTouchesInView = false. Isso resolveu isso para mim, pelo menos. Espero que isso ajude alguém
Quantm

10
"Confira meu repo" é o novo "Hears my new mixtape": P
Josh

118

Uma resposta para sua pergunta sobre como descartar o teclado no Xcode 6.1 usando o Swift abaixo:

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)
    }

}

( Fonte desta informação ).


6
Ótimo pedaço de código, obrigado! touchesBegan foi exatamente o que eu estava procurando :)
Lukasz Czerwinski

4
Isso não funcionou muito para mim. Se eu tocar na visualização do controlador de exibição, ela funcionará. Se eu tocar em um item de controle na exibição, o teclado não será descartado.
user3731622

Esta é a melhor resposta que eu já usei até agora! Esta resposta deve ser marcada como correta. Valeu cara!
wagng

Esta é a melhor solução que eu já vi até agora. Nota pequena: no Swift mais recente, a assinatura de substituição mudou um pouco. Você precisa adicionar _ antes de toques: substituir função touchesBegan (_ toques: Set <UITouch>, com eventoEvent: UIEvent?)
Regis St-Gelais

11
Este provavelmente deve estar marcado como correto. A resposta atual aceita faz com que todos os botões na exibição não respondam quando o teclado está sendo exibido.
Bartek Spitza 07/03/19

39

Swift 4 trabalhando

Crie um ramal como abaixo e ligue hideKeyboardWhenTappedAround()no seu controlador de exibição Base.

//
//  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)
    }
}

O mais importante é chamar o seu Controlador de exibição de base, para que você não precise ligar o tempo todo em todos os controladores de exibição.


36

Você pode ligar

resignFirstResponder()

em qualquer instância de um UIResponder, como um UITextField. Se você chamá-lo na exibição que atualmente está causando a exibição do teclado, o teclado será descartado.


5
Em uma situação em que você não conhece exatamente o primeiro respondedor, resignFirstResponder () pode levar a um monte de problemas. A resposta de Esq abaixo (usando view.doneEditing ()) é muito mais apropriado
shiser

11
Sempre que uso resignFirstResponder no meu textField, o aplicativo trava. Tentei de tudo em que pude pensar e procurei na Web uma solução. Nada me ajuda. Você saberia por que isso acontece?
AugustoQ 23/09

11
Como disse a shiser, essa não é a melhor solução. além disso, não funciona em todas as situações.
Alix

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
    }

}

touchesBegan trabalhou para mim para finalizar a edição do campo de texto e da visualização de texto. Obrigado
Sanju

É isso que eu uso, simples. Remova também os códigos não relacionados para se concentrar na solução.
perfil completo de John Doe

19

para Swift 3 é muito simples

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

se você deseja ocultar o teclado ao pressionar a tecla RETURN

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

mas, no segundo caso, você também precisará passar o delegado de todos os campos de texto para o ViewController no Main.Storyboard


Eu entendo unrecognized selector sent to instancecom esse código.
Haring10

11

Swift 3: maneira mais fácil de descartar o teclado:

  //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
    }

11
Tenho certeza de que a chamada view.endEditing (true) é mais simples, pois não exige que você armazene uma variável ou presuma que você tenha apenas um campo de texto.
Glenn Howes

10

A resposta de Dash é correta e preferida. Uma abordagem mais "abrasadora" é chamar view.endEditing(true). Isso causa viewe todas as suas subvisões para resignFirstResponder. Se você não tem uma referência à visualização que gostaria de descartar, esta é uma solução hacky, mas eficaz.

Observe que, pessoalmente, acho que você deve ter uma referência à exibição que gostaria de renunciar à resposta. .endEditing(force: Bool)é uma abordagem bárbara; por favor não use.


10

swift 5 apenas duas linhas é suficiente. Adicionar ao seu viewDidLoaddeve funcionar.

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

Se o seu gesto de toque bloquear outros toques, adicione esta linha:

tapGesture.cancelsTouchesInView = false

Solução muito simples e elegante :), deve ser a resposta aqui.
Joseph Astrahan

9

No storyboard:

  1. selecione o TableView
  2. no lado direito, selecione o inspetor de atributos
  3. na seção do teclado - selecione o modo de dispensa desejado

não consegue encontrar esse item, onde está e como ele é? Estou no Inspetor de atributo de um textField
Ethan Parker

Você precisa olhar para o TableView não TextField
zevij

9

Swift 3:

Extensão com Selectorcomo parâmetro para poder fazer coisas adicionais na função de descartar e cancelsTouchesInViewevitar distorções com toques em outros elementos da vista.

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

Uso:

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

func dismissKeyboard() {
    view.endEditing(true)
    // do aditional stuff
}

9

Use o IQKeyboardmanager que o ajudará a resolver problemas fáceis .....

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

! [como desativar o teclado ..] [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)
  }
}

8

Encontrei que a melhor solução incluía a resposta aceita do @Esqarrouth, com alguns ajustes:

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

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

A linha tap.cancelsTouchesInView = falseera crítica: assegura que UITapGestureRecognizernão impeça que outros elementos na exibição recebam interação do usuário.

O método dismissKeyboard()foi alterado para um pouco menos elegante dismissKeyboardView(). Isso ocorre porque na base de código bastante antiga do meu projeto, houve várias vezes em que dismissKeyboard()já foi usada (acho que isso não é incomum), causando problemas no compilador.

Então, como acima, esse comportamento pode ser ativado em Controladores de exibição individuais:

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

7

Se você usar uma exibição de rolagem, poderá ser muito mais simples.

Basta selecionar Dismiss interactivelyno storyboard.


7

No Swift 4, adicione @objc:

No viewDidLoad:

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

Função:

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

7

Adicione esta extensão ao seu 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

Para expandir a resposta de Esqarrouth , eu sempre uso o seguinte para descartar o teclado, especialmente se a classe da qual estou descartando o teclado não possui uma viewpropriedade e / ou não é uma subclasse deUIView .

UIApplication.shared.keyWindow?.endEditing(true)

E, por conveniência, a seguinte extensão da UIApplcationclasse:

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)
    }

}

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

Como programador iniciante, pode ser confuso quando as pessoas produzem respostas mais hábeis e desnecessárias ... Você não precisa fazer nada do complicado mostrado acima! ...

Aqui está a opção mais simples ... Caso o teclado apareça em resposta ao campo de texto - Dentro da função da tela de toque, adicione a função resignFirstResponder . Como mostrado abaixo - o teclado será fechado porque o Primeiro Respondente for liberado (saindo da cadeia do Respondente) ...

override func touchesBegan(_: Set<UITouch>, with: UIEvent?){
    MyTextField.resignFirstResponder()
}

5

Eu uso IQKeyBoardManagerSwift para teclado. É fácil de usar. basta adicionar o pod 'IQKeyboardManagerSwift'

Importe IQKeyboardManagerSwift e escreva o código didFinishLaunchingWithOptionsem AppDelegate.

///add this line 
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
IQKeyboardManager.shared.enable = true

4

Este liner renuncia o teclado de todos (qualquer) o UITextField em um UIView

self.view.endEditing(true)

4

Apenas uma linha de código no viewDidLoad()método:

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))

4

Em rápido você pode usar

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

}

3

Para Swift3

Registrar um reconhecedor de eventos em viewDidLoad

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

precisamos adicionar o gesto na visualização no mesmo viewDidLoad.

self.view.addGestureRecognizer(tap)

Então precisamos inicializar o método registrado

func hideKeyBoard(sender: UITapGestureRecognizer? = nil){
    view.endEditing(true)
}

11
Obrigado pela resposta completa e com notas. Esta é a única solução que funcionou para mim.
23418 zeeshan

3

A postagem como uma nova resposta desde que minha edição da resposta de @ King-Wizard foi rejeitada.

Faça da sua turma um delegado do UITextField e substitua o touchesBegan.

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

Você também pode adicionar um reconhecedor de gesto de toque para renunciar ao teclado. : 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")
}

2

Outra possibilidade é simplesmente adicionar um botão grande sem conteúdo que esteja abaixo de todas as visualizações que você possa precisar tocar. Dê a ele uma ação chamada:

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

O problema com um reconhecedor de gestos era para mim, que também captou todos os toques que eu queria receber pelo tableViewCells.


2

Se você tiver outras visualizações que também receberão o toque, precisará definir cancelsTouchesInView = false

Como isso:

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

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

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

}

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

Tente isso, está funcionando


1

Quando houver mais de um campo de texto na exibição

Para seguir a recomendação do @ modocache para evitar chamadasview.endEditing() , você pode acompanhar o campo de texto que se tornou o primeiro respondedor, mas isso é confuso e propenso a erros.

Uma alternativa é chamar resignFirstResponder() todos os campos de texto no controlador de exibição . Aqui está um exemplo de criação de uma coleção de todos os campos de texto (que, no meu caso, eram necessários para o código de validação):

@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]
}

Com a coleção disponível, é simples iterar por todos eles:

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

Agora você pode chamar dismissKeyboard()seu reconhecedor de gestos (ou onde for apropriado). A desvantagem é que você deve manter a lista de UITextFields ao adicionar ou remover campos.

Comentários bem-vindos. Se houver um problema ao chamar os resignFirstResponder()controles que não são os primeiros a responder, ou se houver uma maneira fácil e garantida, sem bugs, de rastrear o atual primeiro respondedor, eu adoraria ouvir sobre isso!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.