【问题标题】:How to dismiss keyboard when touching anywhere outside UITextField (in swift)?触摸 UITextField 以外的任何地方时如何关闭键盘(快速)?
【发布时间】:2026-01-21 18:50:01
【问题描述】:

我正在开发一个具有 UIViewController 的项目,在视图控制器上,滚动视图上有一个 UIScrollView 和一个 UITextField。 像这样: 在文本字段中输入一些文本并点击文本字段外的任何位置后,我试图关闭键盘并将其隐藏。 我试过以下代码:

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

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

当我在滚动视图之外点击时它对我有用,但是当我点击滚动视图时没有任何反应并且键盘不会隐藏。

在文本字段外点击anywhere时,有什么方法可以关闭键盘? 谢谢

【问题讨论】:

    标签: ios swift uitextfield uikeyboard


    【解决方案1】:

    在这种情况下,UITapGesture 作为选项之一。我试图创建示例代码以防万一。像这样,

    class ViewController: UIViewController {
    
        @IBOutlet weak var textField: UITextField!
        @IBOutlet weak var scrollView: UIScrollView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            let tapGesture = UITapGestureRecognizer(target: self, action: "tap:")
            view.addGestureRecognizer(tapGesture)
        }
    
        func tap(gesture: UITapGestureRecognizer) {
            textField.resignFirstResponder()
        }
    }
    

    【讨论】:

    • 感谢它的工作。但我还有另一个问题,我有一个带有 5 个文本字段的视图控制器。有没有一种很好的方法来做同样的事情,而不需要一个一个地为他们调用“resignFirstResponder”方法?
    • 另一个问题,当我点击文本字段外的任何地方时,有什么办法可以关闭键盘吗?例如当我点击一个按钮时?
    • @white-hat 你能把这个问题当作另一个问题来问吗?
    • @WhiteHat 将您的 5 个文本字段放在一个出口集合中。然后创建一个对集合进行迭代并在每个文本字段上调用 ​​resignFirstResponder 的 dismissKeyboard 方法。您可以从手势识别器和按钮操作中调用此方法。
    • @WhiteHat ViewController.View 可以调用 endEdting
    【解决方案2】:

    我在 Obj-C 中创建了这个方法,无论用户当前在哪里输入,它都会隐藏键盘:

    //call this method
    + (void)hideKeyboard {
        //grab the main window of the application
        UIWindow *window = [UIApplication sharedApplication].keyWindow;
        //call our recursive method below
        [self resignResponderForView:window];
    }
    
    //our recursive method
    + (void)resignResponderForView:(UIView *)view {
        //resign responder from this view
        //If it has the keyboard, then it will hide the keyboard
        [view resignFirstResponder];
        //if it has no subviews, then return back up the stack
        if (view.subviews.count == 0)
            return;
        //go through all of its subviews
        for (UIView *subview in view.subviews) {
            //recursively call the method on those subviews
            [self resignResponderForView:subview];
        }
    }
    

    我希望这可以翻译成 Swift 并且有意义。它可以在应用程序中的任何位置调用,无论您使用什么 VC 或任何东西,它都会隐藏键盘。

    【讨论】:

    【解决方案3】:

    转到键盘类型并选择默认或任何您需要的文本字段。然后覆盖一个方法调用它任何你想要的,我通常称之为touchBegins。以下是您忘记添加的内容

    super.touchingBegins(touches, withEvent: event)
     }
    

    【讨论】:

      【解决方案4】:

      试试这个,它已经过测试并且可以工作:

      适用于 Swift 3.0 / 4.0

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

      适用于旧版 Swift

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

      【讨论】:

      • 点击 UIScrollView 时这对我不起作用
      • 请注意,这已更改为在 Swift 2 中覆盖 func touchesBegan(touches: Set, withEvent event: UIEvent?)
      • @WhiteHat 查看我上面的答案,了解适用于 ScrollView 的 Swift 3 答案
      • 这个答案也适用于 Swift 4 !!谢谢。
      • @Hemang 正如@Rao 在对已接受答案的评论中所述,当您拥有 TableView 时,您需要添加 tap.cancelsTouchesInView = false。希望对您有所帮助。
      【解决方案5】:

      我遇到了同样的问题,我终于解决了!

      在 Storyboard 中设置 TapGestureRecognizer,然后在 ViewController 中设置 Outlet

      @IBOutlet var tapGesture: UITapGestureRecognizer!
      

      然后在你的 ViewController 中设置一个 IBAction

      @IBAction func DismissKeyboard(sender: UITapGestureRecognizer)
      {
       self.view.endEditing(true)
      } 
      

      将这些行添加到您的 viewDidLoad 方法中

      override func viewDidLoad()
      {
          super.viewDidLoad()
          self.view.addGestureRecognizer(tapGesture)
      }
      

      它应该可以工作

      希望这会有所帮助!

      【讨论】:

        【解决方案6】:

        为 Swift 4 编辑

        编辑:添加了@objc。虽然这不是性能的最佳选择,但在有更好的解决方案之前,这里的一个实例应该不会造成太多问题。

        在需要与 GestureRecognizer 后面的项目交互时进行了修复。

        编辑:感谢@Rao 指出这一点。已添加tap.cancelsTouchesInView = false

        这应该有助于您拥有多个 UITextViewUITextField

        创建视图控制器的扩展。与尝试使用 .resignFirstResponder() 相比,这对我来说更顺畅,而且麻烦更少

        extension UIViewController
        {
            func setupToHideKeyboardOnTapOnView()
            {
                let tap: UITapGestureRecognizer = UITapGestureRecognizer(
                    target: self,
                    action: #selector(UIViewController.dismissKeyboard))
        
                tap.cancelsTouchesInView = false
                view.addGestureRecognizer(tap)
            }
        
            @objc func dismissKeyboard()
            {
                view.endEditing(true)
            }
        }
        

        在 viewDidLoad 中调用self.setupToHideKeyboardOnTapOnView()

        【讨论】:

        • 工作精美且优雅。这应该是答案
        • 我不得不在 Swift 4 中添加 @objc funcdismissKeyboard()
        • @MCR 你是对的。我更新了答案以反映这一点,直到找到更明确的方法。
        • 警告:如果您说,同一视图上的 tableView,此代码将阻止单元格点击,并且您的 didSelectRow 不会触发。为了避免这种情况,您需要在 addGestureRecognizer 之前添加 tap.cancelsTouchesInView = false
        • 有谁知道如何防止dismissKeyboard() 被调用,如果点击是在一个嵌入在self 中的UIViewContainer 的视图中完成的?
        【解决方案7】:

        文本域每次触摸都不同,关闭键盘或使用resignfirstresponder

        - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
        {
         UITouch *touch = [touches anyObject];
         if(![touch.view isMemberOfClass:[UITextField class]]) {
             [touch.view endEditing:YES];
         }
        }
        

        【讨论】:

          【解决方案8】:

          当在输入区域外触摸任意数量的输入项时,此方法有效。

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

          【讨论】:

            【解决方案9】:

            引入点击手势识别器并为其设置和操作。

            使用代码:

            nameofyourtextfield.resignfirstresponder()

            【讨论】:

              【解决方案10】:

              适用于 ScrollView 的 Swift 3 工作解决方案

              class ViewController: UIViewController {
              
                  @IBOutlet weak var textField: UITextField!
                  @IBOutlet weak var scrollView: UIScrollView!
              
                  override func viewDidLoad() {
                      super.viewDidLoad()
              
                      // The next line is the crucial part
                      // The action is where Swift 3 varies from previous versions
                      let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tap(gesture:)))
                      self.view.addGestureRecognizer(tapGesture)
                  }
              
                  func tap(gesture: UITapGestureRecognizer) {
                      textField.resignFirstResponder()
                  }
              }
              

              另一个question 谈到了我引用和使用的这个问题。接受的答案在 Swift 3 中不再有效。当前选择的答案应该是以下答案。

              【讨论】:

              • @JoeBlow 我相信你错了。您应该辞去 textField 的第一响应者的职务。不是景色。我在我当前的项目中有这个代码,只是在一个新项目中测试了它。更不用说,我的答案只是 Pixyzehn 写的答案的更新版本。
              • 嘿,开发者@Devbot10 - 不要犹豫,将其编辑回您之前的内容。你知道,我可能对.endEditing 感到困惑,它确实在下面的所有视图中递归。
              【解决方案11】:

              详情

              • Xcode 10.2.1 (10E1001)、Swift 5

              解决方案 1

              endEditing(_:)

              let gesture = UITapGestureRecognizer(target: tableView, action: #selector(UITextView.endEditing(_:)))
              tableView.addGestureRecognizer(gesture)
              

              溶液的使用1.全样

              import UIKit
              
              class ViewController: UIViewController {
              
                  override func viewDidLoad() {
                      super.viewDidLoad()
                      let textField = UITextField(frame: CGRect(x: 50, y: 50, width: 200, height: 30))
                      textField.borderStyle = .roundedRect
                      textField.placeholder = "Enter text"
                      textField.becomeFirstResponder()
                      view.addSubview(textField)
                      let gesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:)))
                      view.addGestureRecognizer(gesture)
                  }
              }
              

              解决方案 2

              类 TapGestureRecognizer

              import UIKit
              
              class TapGestureRecognizer: UITapGestureRecognizer {
              
                  let identifier: String
              
                  init(target: Any?, action: Selector?, identifier: String) {
                      self.identifier = identifier
                      super.init(target: target, action: action)
                  }
              
                  static func == (left: TapGestureRecognizer, right: TapGestureRecognizer) -> Bool {
                      return left.identifier == right.identifier
                  }
              }
              

              扩展 UIView

              import UIKit
              
              extension UIView {
              
                  private var hideKeybordOnTapIdentifier: String { return "hideKeybordOnTapIdentifier" }
              
                  private var hideKeybordOnTapGestureRecognizer: TapGestureRecognizer? {
                      let hideKeyboardGesture = TapGestureRecognizer(target: self, action: #selector(UIView.hideKeyboard),
                                                                     identifier: hideKeybordOnTapIdentifier)
                      if let gestureRecognizers = self.gestureRecognizers {
                          for gestureRecognizer in gestureRecognizers {
                              if let tapGestureRecognizer = gestureRecognizer as? TapGestureRecognizer,
                                  tapGestureRecognizer == hideKeyboardGesture {
                                  return tapGestureRecognizer
                              }
                          }
                      }
                      return nil
                  }
              
                  @objc private func hideKeyboard() { endEditing(true) }
              
                  var hideKeyboardOnTap: Bool {
                      set {
                          let hideKeyboardGesture = TapGestureRecognizer(target: self, action: #selector(hideKeyboard),
                                                                         identifier: hideKeybordOnTapIdentifier)
                          if let hideKeybordOnTapGestureRecognizer = hideKeybordOnTapGestureRecognizer {
                              removeGestureRecognizer(hideKeybordOnTapGestureRecognizer)
                              if gestureRecognizers?.count == 0 { gestureRecognizers = nil }
                          }
                          if newValue { addGestureRecognizer(hideKeyboardGesture) }
                      }
                      get { return hideKeybordOnTapGestureRecognizer == nil ? false : true }
                  }
              }
              

              解决方案2的使用

              view.hideKeyboardOnTap = true
              

              解决方案 2 完整示例

              import UIKit
              
              class ViewController: UIViewController {
              
                  override func viewDidLoad() {
                      super.viewDidLoad()
                      let textField = UITextField(frame: CGRect(x: 50, y: 50, width: 200, height: 30))
                      textField.borderStyle = .roundedRect
                      textField.placeholder = "Enter text"
                      textField.becomeFirstResponder()
                      view.addSubview(textField)
                      view.hideKeyboardOnTap = true
                  }
              }
              

              【讨论】:

                【解决方案12】:

                看看这个。

                override func viewDidLoad() {
                    var tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap))
                    self.view.userInteractionEnabled = true
                    self.view.addGestureRecognizer(tapGesture)
                }
                

                那么你的点击处理程序就是。

                  func handleTap(sender: UITapGestureRecognizer) {
                    self.view.endEditing(true)
                }
                

                【讨论】:

                • imgView.addGestureRecognizer(tapGesture) 应该是self.view.addGestureRecognizer(tapGesture)
                • 是的,对不起,我没有注意到。我在输入什么。谢谢@AhsanEbrahim
                【解决方案13】:

                斯威夫特 3

                override func viewDidLoad() {
                    super.viewDidLoad()
                    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
                }
                

                【讨论】:

                  【解决方案14】:
                  func findAndResignFirstResponder(_ stView: UIView) -> Bool {
                  
                      if stView.isFirstResponder {
                          stView.resignFirstResponder()
                          return true
                      }
                      for subView: UIView in stView.subviews {
                          if findAndResignFirstResponder(subView) {
                              return true
                          }
                      }
                      return false
                  }
                  

                  【讨论】:

                    【解决方案15】:

                    对于 Swift 3

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

                    【讨论】:

                      【解决方案16】:

                      //在 swift 4..它对我有用。

                      func setupKeyboardDismissRecognizer(){
                          let tapRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(searchingActivity.dismissKeyboard))
                      
                          self.view.addGestureRecognizer(tapRecognizer)
                      }
                      
                          @objc func dismissKeyboard()
                          {
                              view.endEditing(true)
                              searchTableView.isHidden = true
                          }
                      

                      //在viewDidLoad中调用这个函数setupKeyboardDismissRecognizer()

                      【讨论】:

                        【解决方案17】:

                        在 Swift4 中

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

                        【讨论】:

                          【解决方案18】:

                          在 Swift 4 或 5 中你可以使用 like..

                          class ViewController: UIViewController {
                          
                            override func viewDidLoad() {
                              super.viewDidLoad()
                          
                              //Key borad dismiss
                              let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
                              tap.cancelsTouchesInView = false
                              view.addGestureRecognizer(tap)
                            }
                          
                           //Key board hide on outside the textfield
                           @objc func dismissKeyboard() {
                              //Causes the view (or one of its embedded text fields) to resign the first responder status.
                              view.endEditing(true)
                            }
                          }
                          

                          【讨论】:

                            【解决方案19】:

                            我在 Swift 4 中使用了以下代码,你可以试试这个,

                            override func viewDidLoad() {
                                super.viewDidLoad()
                            
                                // dismiss keyboard when tap outside a text field 
                                let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(YourViewControllerName.dismissKeyboard))
                                view.addGestureRecognizer(tapGestureRecognizer)
                            }
                            
                            //Calls this function when the tap is recognized.
                            func dismissKeyboard() {
                                //Causes the view (or one of its embedded text fields) to resign the first responder status.
                                view.endEditing(true)
                            }
                            

                            【讨论】: