使用Swift触摸任意位置以关闭iOS键盘


407

我一直在寻找这个,但似乎找不到。我知道如何使用来关闭键盘,Objective-C但是我不知道如何使用Swift?有人知道吗?


9
您如何在Objective-C中进行操作?通常,这是从一种语法到另一种语法的转换,很少涉及不同的方法/约定。
Craig Otis 2014年

5
我还没有研究过Swift,但是给我的印象是API都是一样的……
coreyward 2014年

您可能需要检查此答案
艾哈迈德·F

Answers:


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

如果要多次使用此功能,这是另一种执行此任务的方法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


19
由于第一个答案是Swift 2,请替换此行->让我们点击:UITapGestureRecognizer = UITapGestureRecognizer(target:self,action:#selector(MyViewController.dismissKeyboard))
Sam Bellerose

2
它打破了tableviewcontroller上的tableviewcell的
顺序

11
这是我遇到过的最有用的扩展之一!谢谢!我要扩展的唯一警告是,这可能会干扰didSelectRowAtIndexPath
克利夫顿·拉布鲁姆

47
刚刚发现了这个问题并实现了该方法。tableView / UICollectionView的“ didSelectRow”问题没有真正引起我的注意。解决方案是:只需将其添加到您的扩展程序中:tap.cancelsTouchesInView = false。那至少对我来说解决了。希望这对某人有帮助
Quantm

10
“签出我的仓库”是新的“听到我的新混音带”:P
乔什(Josh)2013年

118

有关以下有关如何使用Swift在Xcode 6.1中关闭键盘的问题的答案:

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
很棒的代码,谢谢!touchesBegan正是我想要的东西:)
Lukasz Czerwinski

4
这对我来说不是很有效。如果我点击视图控制器的视图,它将起作用。如果我点击视图中的控件,则不会关闭键盘。
user3731622 '16

这是我到目前为止使用过的最好的答案!该答案应标记为正确。谢啦!
wagng

这是到目前为止我所看到的最好的解决方案。小提示:在较新的Swift中,覆盖签名有所变化。您需要在触摸之前添加_:覆盖func touchesBegan(_ touches:Set <UITouch>,withEvent事件:UIEvent?)
Regis St-Gelais

1
可能应该将此标记为正确的一个。当前接受的答案使显示键盘时视图中的每个按钮都不响应。
Bartek Spitza,

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

在Base View Controller中调用最重要的事情,这样就不需要一直在所有View Controller中调用。


36

你可以打电话

resignFirstResponder()

在UIResponder的任何实例(例如UITextField)上。如果在当前导致键盘显示的视图上调用它,则键盘将关闭。


5
在您不完全了解第一响应者的情况下,resignFirstResponder()可能会导致很多麻烦。esq下面的答案(使用view.doneEditing())更合适
shiser 2015年

1
每当我在textField上使用resignFirstResponder时,应用程序就会崩溃。我尝试了所有可能想到的方法,然后在网上寻找解决方法。没有任何帮助。您是否会知道为什么会这样?
AugustoQ 2015年

1
正如shiser所说,这不是最佳解决方案。而且它并非在所有情况下都有效。
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为我工作,结束了textfield和textview的编辑。谢谢
Sanju

这就是我使用的,很简单。还删除不相关的代码以专注于解决方案。
John Doe

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
}

但是在第二种情况下,您还需要将所有textField的委托传递给Main.Storyboard中的ViewController


我得到unrecognized selector sent to instance了这段代码。
Haring10年10

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
    }

1
我相当确定view.endEditing(true)调用更简单,因为它不需要您存储变量或假定您只有一个文本字段。
Glenn Howes

10

达世币的答案是正确的并且是首选。一个更“焦土”的方法叫做view.endEditing(true)。这导致view及其所有子视图resignFirstResponder。如果您没有要关闭的视图的引用,那么这是一种骇人但有效的解决方案。

请注意,我个人认为您应该参考要辞职的第一视图。.endEditing(force: Bool)是野蛮的方法;请不要使用它。


10

迅速5仅仅两行就足够了。添加到您的viewDidLoad作品中。

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

如果您的点击手势阻止了其他触摸,请添加以下行:

tapGesture.cancelsTouchesInView = false

非常简单而优雅的解决方案:),应该是这里的答案。
约瑟夫·阿斯特拉罕

9

在情节提要中:

  1. 选择TableView
  2. 从右侧选择属性检查器
  3. 在键盘部分-选择所需的关闭模式

找不到该物品,它在哪里,看起来像什么?我在textField的属性检查器中
伊桑·帕克

您需要查看TableView而不是TextField
zevij

9

斯威夫特3:

使用Selectoras参数扩展,以便能够在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)
  }
}

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()被使用(我想这并不罕见),从而导致了编译器问题。

然后,如上所述,可以在各个View Controller中启用此行为:

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

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

为了扩展Esqarrouth的答案,我总是使用以下命令来关闭键盘,尤其是如果我要从中关闭键盘的类没有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)
    }

}

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用于键盘。它很容易使用。只需添加pod'IQKeyboardManagerSwift'

导入IQKeyboardManagerSwift并在didFinishLaunchingWithOptions中编写代码AppDelegate

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

4

这一衬里从UIView中所有(任意)UITextField退出了Keyboard

self.view.endEditing(true)

4

您可以迅速使用

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
感谢您提供完整的答案和注释。这是唯一对我有用的解决方案。
zeeshan

3

自从我对@ King-Wizard答案的编辑被拒绝后,该帖子已发布为新答案。

使您的类成为UITextField的委托,并覆盖touchesBegan。

斯威夫特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)
    }

}

3

方法中只有一行代码viewDidLoad()

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

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

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)

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()手势识别器(或适合您的位置)。缺点是UITextField添加或删除字段时必须维护的列表。

欢迎发表评论。如果调用resignFirstResponder()不是第一响应者的控件有问题,或者有一种简单且有保证的非笨拙的方式来跟踪当前的第一响应者,我很乐意听到!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.