Zamknij klawiaturę iOS, dotykając dowolnego miejsca za pomocą Swift

407

Szukałem tego wszystkiego, ale nie mogę tego znaleźć. Wiem, jak zamknąć klawiaturę, Objective-Cale nie mam pojęcia, jak to zrobić Swift? Czy ktoś wie?

laguna
źródło
9
Jak sobie radzisz w Objective-C? Zwykle jest to konwersja jednej składni na drugą i rzadko jest to kwestia różnych metod / konwencji.
Craig Otis
5
Nie kopałem w Swift, ale miałem wrażenie, że interfejs API jest taki sam…
coreyward
Możesz sprawdzić tę odpowiedź .
Ahmad F,

Odpowiedzi:

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

Oto inny sposób wykonania tego zadania, jeśli zamierzasz korzystać z tej funkcji na wiele sposobów 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)
    }
}

Teraz UIViewControllerwystarczy, że wywołasz tę funkcję:

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

Ta funkcja jest zawarta jako standardowa funkcja w moim repozytorium, która zawiera wiele przydatnych rozszerzeń Swift, takich jak ta, sprawdź: https://github.com/goktugyil/EZSwiftExtensions

Esqarrouth
źródło
19
Od Swift 2 w pierwszej odpowiedzi zamień ten wiersz-> pozwól, aby: UITapGestureRecognizer = UITapGestureRecognizer (cel: jaźń, akcja: #selector (MyViewController.dismissKeyboard))
Sam Bellerose
2
łamie segregację tableviewcell na kontrolerze tableview
Utku Dalmaz
11
To jedno z najbardziej pomocnych rozszerzeń, jakie kiedykolwiek spotkałem! Dziękuję Ci! Jedyną ostrożnością, którą chciałbym poruszyć, jest to, że może to kolidować didSelectRowAtIndexPath.
Clifton Labrum,
47
Właśnie odkryłem to pytanie i wdrożyłem tę metodę. To, że „didSelectRow” tableView / UICollectionView nie dzwonił dosłownie doprowadzało mnie do szału. Rozwiązaniem jest: Wystarczy dodać do tego rozszerzenia: tap.cancelsTouchesInView = false. To przynajmniej dla mnie rozwiązało. Mam nadzieję, że to komuś pomoże
Quantm
10
„Check out my repo” to nowy „Hear my new mixtape”: P
Josh
118

Poniżej znajduje się odpowiedź na pytanie, jak usunąć klawiaturę w Xcode 6.1 za pomocą 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)
    }

}

( Źródło tej informacji ).

King-Wizard
źródło
6
Świetny kawałek kodu, dzięki! touchesBegan było dokładnie tym, czego szukałem :)
Łukasz Czerwiński
4
To nie do końca działało. Po dotknięciu widoku kontrolera widoku działa. Jeśli stuknę element sterujący w widoku, klawiatura nie zostanie zwolniona.
user3731622,
To najlepsza odpowiedź, jakiej kiedykolwiek użyłem! Ta odpowiedź powinna być oznaczona jako poprawna. Dzięki stary!
wagng
To najlepsze rozwiązanie, jakie do tej pory widziałem. Mała uwaga: w nowszym Swift podpis zastępujący nieco się zmienił. Musisz dodać _ przed dotknięciem: przesłonięcie func touchBegan (_ dotknięcia: Ustaw <UITouch>, z wydarzeniem Event: UIEvent?)
Regis St-Gelais
1
Ten prawdopodobnie powinien być oznaczony jako poprawny. Obecna akceptowana odpowiedź sprawia, że ​​każdy przycisk w widoku nie reaguje, gdy klawiatura jest wyświetlana.
Bartek Spitza
39

Swift 4 działa

Utwórz rozszerzenie jak poniżej i zadzwoń hideKeyboardWhenTappedAround()w kontrolerze widoku podstawowego.

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

Najważniejsze, aby zadzwonić w kontrolerze widoku podstawowego, aby nie trzeba było dzwonić cały czas we wszystkich kontrolerach widoku.

Fahim Parkar
źródło
36

Możesz zadzwonić

resignFirstResponder()

w dowolnej instancji UIResponder, takiej jak UITextField. Jeśli wywołasz go w widoku, który obecnie powoduje wyświetlenie klawiatury, klawiatura się odłączy.

Dziarskość
źródło
5
W sytuacji, gdy nie znasz dokładnie pierwszego odpowiadającego, resignFirstResponder () może prowadzić do kłopotów. Odpowiedź Esq poniżej (za pomocą view.doneEditing ()) jest o wiele bardziej odpowiednia
shiser
1
Ilekroć używam resignFirstResponder na textField, aplikacja ulega awarii. Próbowałem wszystkiego, co mogłem wymyślić, i szukałem poprawki w Internecie. Nic mi nie pomaga. Czy wiesz, dlaczego tak się dzieje?
AugustoQ,
1
Jak powiedział shiser, nie jest to najlepsze rozwiązanie. a ponadto nie działa we wszystkich sytuacjach.
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
    }

}
Naishta
źródło
touchesBegan pracował dla mnie, aby zakończyć edycję pola tekstowego i widoku tekstu. Dzięki
Sanju,
Tego używam, proste. Usuń także niepowiązane kody, aby skupić się na rozwiązaniu.
John Doe,
19

w przypadku Swift 3 jest to bardzo proste

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

jeśli chcesz ukryć klawiaturę po naciśnięciu klawisza RETURN

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

ale w drugim przypadku musisz także przekazać delegata ze wszystkich pól tekstowych do ViewController w Main.Storyboard

Yerbol
źródło
Dostaję unrecognized selector sent to instancez tym kodem.
Haring10
11

Swift 3: Najłatwiejszy sposób na wyłączenie klawiatury:

  //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
źródło
1
Jestem całkiem pewien, że wywołanie view.endEditing (true) jest prostsze, ponieważ nie wymaga zapisywania zmiennej ani zakładania, że ​​masz tylko jedno pole tekstowe.
Glenn Howes
10

Odpowiedź Dash'a jest poprawna i preferowana. Bardziej „spieczona ziemia” to podejście view.endEditing(true). To powoduje viewi wszystkie jego podviews do resignFirstResponder. Jeśli nie masz odniesienia do widoku, który chcesz odrzucić, jest to hackerskie, ale skuteczne rozwiązanie.

Pamiętaj, że osobiście uważam, że powinieneś mieć odniesienie do widoku, który chcesz zrezygnować z pierwszej odpowiedzi. .endEditing(force: Bool)jest barbarzyńskim podejściem; proszę nie używać tego.

pamięć podręczna
źródło
10

swift 5 wystarczy dwie linie. Dodaj do viewDidLoadpowinien działać.

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

Jeśli gest stuknięcia zablokował inne dotknięcia, dodaj następujący wiersz:

tapGesture.cancelsTouchesInView = false
William Hu
źródło
Bardzo proste i eleganckie rozwiązanie :), powinna być odpowiedź tutaj.
Joseph Astrahan
9

W scenorysie:

  1. wybierz TableView
  2. z prawej strony wybierz inspektora atrybutów
  3. w sekcji klawiatury - wybierz żądany tryb odrzucania
zevij
źródło
nie mogę znaleźć tego przedmiotu, gdzie on jest i jak wygląda? Jestem w inspektorze atrybutów pola tekstowego
Ethan Parker,
Musisz spojrzeć na TableView, a nie TextField
zevij,
9

Swift 3:

Rozszerzenie z Selectorparametrem umożliwiającym wykonywanie dodatkowych czynności w funkcji zwalniania i cancelsTouchesInViewzapobieganie zniekształceniom przy dotknięciach innych elementów widoku.

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

Stosowanie:

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

func dismissKeyboard() {
    view.endEditing(true)
    // do aditional stuff
}
David Seek
źródło
9

Użyj IQKeyboardmanager , który pomoże ci rozwiązać proste .....

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

! [jak wyłączyć klawiaturę ..] [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
źródło
8

Znalazłem najlepsze rozwiązanie z zaakceptowaną odpowiedzią @Esqarrouth, z pewnymi poprawkami:

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

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

Linia tap.cancelsTouchesInView = falsebyła krytyczna: zapewnia, że UITapGestureRecognizernie uniemożliwia innym elementom widoku interakcji z użytkownikiem.

Metodę dismissKeyboard()zmieniono na nieco mniej elegancką dismissKeyboardView(). Jest tak, ponieważ w dość starej bazie kodu mojego projektu wiele razy dismissKeyboard()był już używany (wyobrażam sobie, że nie jest to rzadkie), powodując problemy z kompilatorem.

Następnie, jak wyżej, to zachowanie można włączyć w poszczególnych kontrolerach widoku:

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround() 
}
Luke Harries
źródło
7

Jeśli używasz widoku przewijania, może to być znacznie prostsze.

Po prostu wybierz Dismiss interactivelyw serii ujęć.

JIE WANG
źródło
7

W Swift 4 dodaj @objc:

W viewDidLoad:

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

Funkcjonować:

@objc func dismissKeyboard() {
  view.endEditing(true)
}
użytkownik3856297
źródło
7

Dodaj to rozszerzenie do 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)
  }
}
Jarvis The Avenger
źródło
6

Aby rozwinąć odpowiedź Esqarrouth , zawsze używam następującego polecenia, aby zamknąć klawiaturę, szczególnie jeśli klasa, z której zwalniam klawiaturę , nie ma viewwłaściwości i / lub nie jest podklasąUIView .

UIApplication.shared.keyWindow?.endEditing(true)

I dla wygody następujące rozszerzenie UIApplcationklasy:

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
źródło
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)
  }
}
Prashant chaudhary
źródło
5

Jako początkujący programista może być mylące, gdy ludzie produkują bardziej wykwalifikowane i niepotrzebne odpowiedzi ... Nie musisz wykonywać żadnych skomplikowanych czynności pokazanych powyżej! ...

Oto najprostsza opcja ... W przypadku pojawienia się klawiatury w odpowiedzi na pole tekstowe - Wewnątrz funkcji ekranu dotykowego wystarczy dodać funkcję resignFirstResponder . Jak pokazano poniżej - klawiatura zostanie zamknięta, ponieważ zwolniony jest pierwszy obiekt odpowiadający (wyjście z łańcucha obiektu odpowiadającego) ...

override func touchesBegan(_: Set<UITouch>, with: UIEvent?){
    MyTextField.resignFirstResponder()
}
Czerwone niebo
źródło
5

Używam IQKeyBoardManagerSwift dla klawiatury. jest łatwy w użyciu. wystarczy dodać pod „IQKeyboardManagerSwift”

Zaimportuj IQKeyboardManagerSwift i napisz kod didFinishLaunchingWithOptionsw AppDelegate.

///add this line 
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
IQKeyboardManager.shared.enable = true
Sukhwinder Singh
źródło
4

Ta jedna linijka rezygnuje z klawiatury ze wszystkich (dowolnych) pól UITextField w UIView

self.view.endEditing(true)
Karta
źródło
4

W szybki sposób możesz użyć

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

}
Bernard Rayoso
źródło
3

Dla Swift3

Zarejestruj moduł rozpoznawania zdarzeń w viewDidLoad

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

następnie musimy dodać gest do widoku w tym samym viewDidLoad.

self.view.addGestureRecognizer(tap)

Następnie musimy zainicjować zarejestrowaną metodę

func hideKeyBoard(sender: UITapGestureRecognizer? = nil){
    view.endEditing(true)
}
Sandu
źródło
1
Dzięki za pełną odpowiedź i notatki. To jedyne rozwiązanie, które działało dla mnie.
zeeshan
3

Publikowanie jako nowej odpowiedzi, ponieważ moja edycja odpowiedzi @ King-Wizard została odrzucona.

Uczyń swoją klasę delegatem UITextField i unieważnij touchBEG.

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

}
Viktor Seč
źródło
3

Tylko jeden wiersz kodu w viewDidLoad()metodzie:

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
Artem
źródło
2

Możesz także dodać rozpoznawanie gestów, aby zrezygnować z klawiatury. :RE

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")
}
Karta
źródło
2

Inną możliwością jest po prostu dodanie dużego przycisku bez treści, która leży pod wszystkimi widokami, których możesz potrzebować dotknąć. Daj mu akcję o nazwie:

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

Problem z rozpoznawaniem gestów był dla mnie taki, że przechwytywał on także wszystkie dotknięcia, które chciałem otrzymać przez tableViewCells.

Timm Kent
źródło
2

Jeśli masz inne widoki, które również powinny zostać dotknięte, musisz je ustawić cancelsTouchesInView = false

Lubię to:

let elsewhereTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    elsewhereTap.cancelsTouchesInView = false
    self.view.addGestureRecognizer(elsewhereTap)
ph1lb4
źródło
2
override func viewDidLoad() {
        super.viewDidLoad()

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

}

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

Spróbuj tego, działa

Ramprasath Selvam
źródło
1

Gdy w widoku jest więcej niż jedno pole tekstowe

Aby postępować zgodnie z zaleceniami @ modocache, aby uniknąć dzwonienia view.endEditing(), możesz śledzić pole tekstowe, które stało się pierwszą odpowiedzią, ale jest niechlujne i podatne na błędy.

Alternatywą jest wywołanie resignFirstResponder() wszystkich pól tekstowych w kontroler widoku . Oto przykład tworzenia kolekcji wszystkich pól tekstowych (które w moim przypadku i tak były potrzebne do kodu weryfikacyjnego):

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

Z dostępną kolekcją iteracja wszystkich z nich jest prosta:

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

Teraz możesz zadzwonić dismissKeyboard()w swoim rozpoznawaniu gestów (lub w dowolnym innym miejscu). Wadą jest to, że musisz zachować listę UITextFields podczas dodawania lub usuwania pól.

Komentarze mile widziane. Jeśli występuje problem z wywołaniem resignFirstResponder()elementów sterujących, które nie reagują jako pierwsze, lub jeśli istnieje łatwy i gwarantowany niezawodny sposób na śledzenie bieżącego pierwszego reagującego, chciałbym o tym usłyszeć!

złóg
źródło