Tutup iOS Keyboard dengan menyentuh di mana saja menggunakan Swift

409

Saya sudah mencari-cari ini tapi sepertinya saya tidak bisa menemukannya. Saya tahu cara menghapus keyboard menggunakan Objective-Ctetapi saya tidak tahu bagaimana melakukannya dengan menggunakan Swift? Apakah ada yang tahu?

laguna
sumber
9
Bagaimana Anda melakukannya di Objective-C? Biasanya konversi dari satu sintaks ke yang lain, dan jarang masalah metode / konvensi yang berbeda.
Craig Otis
5
Saya belum menggali Swift, tetapi saya mendapat kesan bahwa
APInya
Anda mungkin ingin memeriksa jawaban ini .
Ahmad F

Jawaban:

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

Berikut adalah cara lain untuk melakukan tugas ini jika Anda akan menggunakan fungsi ini secara berganda 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)
    }
}

Sekarang di setiap UIViewController, yang harus Anda lakukan adalah memanggil fungsi ini:

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

Fungsi ini dimasukkan sebagai fungsi standar dalam repo saya yang berisi banyak Ekstensi Swift yang bermanfaat seperti ini, periksa: https://github.com/goktugyil/EZSwiftExtensions

Esqarrouth
sumber
19
Karena Swift 2 dalam jawaban pertama, ganti baris ini-> biarkan ketuk: UITapGestureRecognizer = UITapGestureRecognizer (target: mandiri, tindakan: #selector (MyViewController.dismissKeyboard))
Sam Bellerose
2
itu merusak segue tableviewcell pada tableviewcontroller
Utku Dalmaz
11
Ini adalah salah satu ekstensi paling bermanfaat yang pernah saya temui! Terima kasih! Satu-satunya peringatan saya akan memperpanjang adalah bahwa ini dapat mengganggu didSelectRowAtIndexPath.
Clifton Labrum
47
Baru saja menemukan pertanyaan ini dan menerapkan metode itu. Hal itu dengan "didSelectRow" dari tableView / UICollectionView tidak menelepon secara harfiah membuat saya gila. Solusinya adalah: Cukup menambahkan ini ke ekstensi Anda: tap.cancelsTouchesInView = false. Setidaknya itu menyelesaikannya untuk saya. Semoga ini bisa membantu seseorang
Quantm
10
"Check out my repo" adalah yang baru "Hears my mixtape baru": P
Josh
118

Jawaban atas pertanyaan Anda tentang cara mengabaikan keyboard di Xcode 6.1 menggunakan Swift di bawah ini:

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

}

( Sumber informasi ini ).

Raja-Penyihir
sumber
6
Sepotong kode hebat, terima kasih! touchesBegan adalah apa yang saya cari :)
Lukasz Czerwinski
4
Ini tidak berhasil bagi saya. Jika saya mengetuk tampilan pengontrol tampilan itu berfungsi. Jika saya mengetuk item kontrol di tampilan, keyboard tidak mau mengabaikan.
user3731622
Ini adalah jawaban terbaik yang pernah saya gunakan sejauh ini! Jawaban ini harus ditandai sebagai benar. Terima kasih sobat!
Wagng
Ini adalah solusi terbaik yang saya lihat sejauh ini. Catatan kecil: di Swift yang lebih baru tanda tangan override berubah sedikit. Anda perlu menambahkan _ sebelum menyentuh: override func touchesBegan (_ sentuhan: Set <UITouch>, withEvent acara:? UIEvent)
Regis St-Gelais
1
Yang ini mungkin harus ditandai sebagai yang benar. Jawaban yang diterima saat ini membuat setiap tombol dalam tampilan tidak responsif saat keyboard ditampilkan.
Bartek Spitza
39

Swift 4 bekerja

Buat ekstensi seperti di bawah ini & panggil hideKeyboardWhenTappedAround()di pengontrol tampilan Base Anda.

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

Paling penting untuk memanggil di Base View Controller Anda sehingga tidak perlu menelepon sepanjang waktu di semua pengontrol tampilan.

Fahim Parkar
sumber
36

Anda bisa menelepon

resignFirstResponder()

pada instance UIResponder, seperti UITextField. Jika Anda menyebutnya pada tampilan yang saat ini menyebabkan keyboard ditampilkan, maka keyboard tersebut akan diberhentikan.

Berlari
sumber
5
Dalam situasi di mana Anda tidak tahu persis responden pertama, mengundurkan diriFirstResponder () dapat menyebabkan banyak masalah. Jawaban Esq di bawah ini (menggunakan view.doneEditing ()) jauh lebih tepat
shiser
1
Setiap kali saya menggunakan resignFirstResponder di textField, aplikasi saya mogok. Saya mencoba semua yang saya bisa pikirkan, dan mencari di internet untuk perbaikan. Tidak ada yang membantu saya. Apakah Anda tahu mengapa itu terjadi?
AugustoQ
1
Seperti kata shiser, ini bukan solusi terbaik. ditambah lagi itu tidak bekerja di semua situasi.
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
sumber
touches Mulai bekerja bagi saya untuk mengakhiri pengeditan bidang teks dan tampilan teks. Terima kasih
Sanju
Ini yang saya gunakan, sederhana. Hapus juga kode yang tidak terkait untuk fokus pada solusi.
John Doe
19

untuk Swift 3 sangat sederhana

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

jika Anda ingin menyembunyikan keyboard saat menekan tombol RETURN

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

tetapi dalam kasus kedua Anda juga harus meneruskan delegasi dari semua textFields ke ViewController di Main.Storyboard

Yerbol
sumber
Saya dapatkan unrecognized selector sent to instancedengan kode ini.
Haring10
11

Swift 3: Cara termudah untuk mengabaikan keyboard:

  //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
sumber
1
Saya cukup yakin bahwa panggilan view.endEditing (true) lebih sederhana karena tidak mengharuskan Anda untuk menyimpan variabel atau menganggap Anda hanya memiliki satu bidang teks.
Glenn Howes
10

Jawaban Dash benar dan disukai. Pendekatan yang lebih "bumi hangus" adalah menelepon view.endEditing(true). Ini menyebabkan viewdan semua subview untuk resignFirstResponder. Jika Anda tidak memiliki referensi ke tampilan yang ingin Anda abaikan, ini adalah solusi yang retas namun efektif.

Perhatikan bahwa secara pribadi saya pikir Anda harus memiliki referensi ke tampilan yang Anda ingin mengundurkan diri sebagai responden pertama. .endEditing(force: Bool)adalah pendekatan biadab; tolong jangan gunakan itu.

modocache
sumber
10

Swift 5 hanya dua baris sudah cukup. Tambahkan ke Anda viewDidLoadharus bekerja.

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

Jika gerakan ketuk Anda memblokir beberapa sentuhan lain, maka tambahkan baris ini:

tapGesture.cancelsTouchesInView = false
William Hu
sumber
Solusi yang sangat sederhana dan elegan :), harus menjadi jawabannya di sini.
Joseph Astrahan
9

Di storyboard:

  1. pilih TableView
  2. dari sisi kanan, pilih pemeriksa atribut
  3. di bagian keyboard - pilih mode pemberhentian yang Anda inginkan
zevij
sumber
tidak dapat menemukan item itu, di mana itu dan seperti apa itu? Saya di inspektur atribut textField
Ethan Parker
Anda harus melihat pada TableView bukan TextField
zevij
9

Swift 3:

Ekstensi dengan Selectorsebagai parameter untuk dapat melakukan hal-hal tambahan dalam fungsi pemberhentian dan cancelsTouchesInViewuntuk mencegah distorsi dengan sentuhan pada elemen lain dari tampilan.

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

Pemakaian:

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

func dismissKeyboard() {
    view.endEditing(true)
    // do aditional stuff
}
David Seek
sumber
9

Gunakan IQKeyboardmanager yang akan membantu Anda menyelesaikan dengan mudah .....

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

! [cara menonaktifkan keyboard ..] [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
sumber
8

Saya menemukan solusi terbaik termasuk jawaban yang diterima dari @Esqarrouth, dengan beberapa penyesuaian:

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

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

Baris tap.cancelsTouchesInView = falsesangat penting: memastikan bahwa UITapGestureRecognizerelemen-elemen lain pada tampilan tidak mencegah interaksi pengguna.

Metode dismissKeyboard()itu diubah menjadi sedikit kurang elegan dismissKeyboardView(). Ini karena dalam basis kode proyek saya yang cukup lama, ada beberapa kali di mana dismissKeyboard()sudah digunakan (saya bayangkan ini tidak biasa), menyebabkan masalah kompiler.

Kemudian, seperti di atas, perilaku ini dapat diaktifkan di Pengontrol Tampilan individual:

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround() 
}
Luke Harries
sumber
7

Jika Anda menggunakan tampilan gulir, Itu bisa jauh lebih sederhana.

Cukup pilih Dismiss interactivelydi storyboard.

JIE WANG
sumber
7

Di Swift 4, tambahkan @objc:

Di viewDidLoad:

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

Fungsi:

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

Tambahkan ekstensi ini ke ViewController Anda:

  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
sumber
6

Untuk memperluas jawaban Esqarrouth , saya selalu menggunakan yang berikut ini untuk mengabaikan keyboard, terutama jika kelas dari mana saya menolak keyboard tidak memiliki viewproperti dan / atau bukan subkelas dariUIView .

UIApplication.shared.keyWindow?.endEditing(true)

Dan, untuk kenyamanan, ekstensi berikut ke UIApplcationkelas:

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
sumber
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
sumber
5

Sebagai seorang programmer pemula dapat membingungkan ketika orang menghasilkan tanggapan yang lebih terampil dan tidak perlu ... Anda tidak perlu melakukan hal-hal rumit yang ditunjukkan di atas! ...

Berikut adalah pilihan paling sederhana ... Jika keyboard Anda muncul sebagai respons terhadap bidang teks - Di dalam fungsi layar sentuh Anda, tambahkan saja fungsi resignFirstResponder . Seperti yang ditunjukkan di bawah ini - keyboard akan ditutup karena Responder Pertama dilepaskan (keluar dari rantai Responder) ...

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

Saya telah menggunakan IQKeyBoardManagerSwift untuk keyboard. mudah digunakan. cukup Tambahkan pod 'IQKeyboardManagerSwift'

Impor IQKeyboardManagerSwift dan tulis kode didFinishLaunchingWithOptionsdi AppDelegate.

///add this line 
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
IQKeyboardManager.shared.enable = true
Sukhwinder Singh
sumber
4

Liner satu ini mengundurkan diri Keyboard dari semua (apa saja) UITextField di UIView

self.view.endEditing(true)
Codetard
sumber
4

Hanya satu baris kode dalam viewDidLoad()metode:

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

Dengan cepat Anda bisa menggunakannya

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

}
bernard rayoso
sumber
3

Untuk Swift3

Daftarkan recogniser acara di viewDidLoad

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

maka kita perlu menambahkan gerakan ke tampilan dalam viewDidLoad yang sama.

self.view.addGestureRecognizer(tap)

Maka kita perlu menginisialisasi metode yang terdaftar

func hideKeyBoard(sender: UITapGestureRecognizer? = nil){
    view.endEditing(true)
}
Sandu
sumber
1
Terima kasih atas jawaban lengkap dan dengan catatan. Ini adalah satu-satunya solusi yang berhasil untuk saya.
zeeshan
3

Posting sebagai jawaban baru karena edit saya pada jawaban @ King-Wizard ditolak.

Jadikan kelas Anda sebagai delegasi dari UITextField dan ganti sentuhanBegan.

Cepat 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č
sumber
2

Anda juga dapat menambahkan pengenal isyarat ketuk untuk mengundurkan diri keyboard. : 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
sumber
2

Kemungkinan lain adalah dengan menambahkan tombol besar tanpa konten yang ada di bawah semua tampilan yang perlu Anda sentuh. Berikan tindakan bernama:

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

Masalah dengan pengenal isyarat bagi saya, itu juga menangkap semua sentuhan yang ingin saya terima oleh tableViewCells.

Timm Kent
sumber
2

Jika Anda memiliki pandangan lain yang harus menerima sentuhan juga Anda harus mengatur cancelsTouchesInView = false

Seperti ini:

let elsewhereTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    elsewhereTap.cancelsTouchesInView = false
    self.view.addGestureRecognizer(elsewhereTap)
ph1lb4
sumber
2
override func viewDidLoad() {
        super.viewDidLoad()

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

}

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

Coba ini, Ini Bekerja

Ramprasath Selvam
sumber
1

Ketika ada lebih dari satu bidang teks dalam tampilan

Untuk mengikuti rekomendasi @ modocache untuk menghindari panggilanview.endEditing() , Anda dapat melacak bidang teks yang menjadi responden pertama, tetapi itu berantakan dan rentan kesalahan.

Alternatifnya adalah memanggil resignFirstResponder() semua bidang teks di viewcontroller . Berikut adalah contoh membuat koleksi semua bidang teks (yang dalam kasus saya diperlukan untuk kode validasi):

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

Dengan koleksi yang tersedia, mudah untuk mengulangi semuanya:

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

Jadi sekarang Anda dapat memanggil dismissKeyboard()pengenal isyarat Anda (atau di mana pun yang sesuai untuk Anda). Kekurangannya adalah Anda harus mempertahankan daftar UITextFieldketika Anda menambah atau menghapus bidang.

Komentar diterima. Jika ada masalah dengan memanggil resignFirstResponder()kontrol yang bukan responden pertama, atau jika ada cara non-kereta yang mudah dan terjamin untuk melacak responden pertama saat ini, saya ingin mendengarnya!

batu
sumber