13

Is it possible to get the currently active UITextField or UITextView in a UIView, so I can hide the keyboard with [text resignFirstResponder];?

memmons
  • 40,222
  • 21
  • 149
  • 183
Tyilo
  • 28,998
  • 40
  • 113
  • 198
  • possible duplicate of [How can I determine the UITextField currently selected?](http://stackoverflow.com/questions/8956704/how-can-i-determine-the-uitextfield-currently-selected) – rob mayoff Jan 22 '12 at 06:22

6 Answers6

27

As of iOS 2.0 and later, there is an easy way to dismiss the keyboard without having to track the currently active control, or iterating through all the available controls, or using a UITextFieldDelegate.

[self.view endEditing:YES]

From the docs:

endEditing:

Causes the view (or one of its embedded text fields) to resign the first responder status.

- (BOOL)endEditing:(BOOL)force

Parameters
force
Specify YES to force the first responder to resign, regardless of whether it wants to do so.

Return Value
YES if the view resigned the first responder status or NO if it did not.

Discussion
This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign.

memmons
  • 40,222
  • 21
  • 149
  • 183
5

This swift code works in finding the first responder:

func findActiveResponderFrame(view:UIView)->UIView?{
  if view.isFirstResponder() {
    return view
  } else {
    for sub in view.subviews {
      if let subView = sub as? UIView,
             found = findActiveResponderFrame(subView){
        return found
      }
    }
  }
  return nil
}
Frank McCabe
  • 51
  • 1
  • 1
5

There is no way to directly get what object is the current first responder (that I know of, at least) without testing them individually. What you can do is to create a method containing all subviews which could conceivably be the active first responder, as follows:

- (void)dismissKeyboard {
    if (myTextField1.isFirstResponder) {
        [myTextField1 resignFirstResponder];
    }
    else if (myTextField2.isFirstResponder) {
        [myTextField2 resignFirstResponder];
    }
    else if (myTextField3.isFirstResponder) {
        [myTextField3 resignFirstResponder];
    }
    else if (myTextField4.isFirstResponder) {
        [myTextField4 resignFirstResponder];
    }
}

In reality, though, I tend to do it this way, without first testing whether a particular UIView is the current first responder, and don't think there is any appreciable performance hit/issue (that I've noticed anyway):

- (void)dismissKeyboard {
    //Send resignFirstResponder message to all possible first responders...
    [myTextField1 resignFirstResponder];
    [myTextField2 resignFirstResponder];
    [myTextField3 resignFirstResponder];
    [myTextField4 resignFirstResponder];
}

Hope that helps...

Ashwin
  • 2,317
  • 1
  • 15
  • 5
0

Update for Swift 3

This function hides the keyboard of any active textfield in Swift 3:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}
Ibrahim
  • 6,006
  • 3
  • 39
  • 50
0

Similar question posted here. I wrote a basic form creation library that handles this and validation. It's called Swift POP Form! It doesn't use tags but rather sets a datasource that contains fields and uses indexPathForCell to query which is the active textfield. Check out the source code for more!

edit: Or as requested heres a snippet from it. This form uses UITextFields embedded in UITableViewCells:

extension PopFormViewController: UITextFieldDelegate {

  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    guard let cell = textField.superview as? PopFormTableViewCell else {
      fatalError() }

    guard let currentIndex = tableView.indexPath(for: cell) else {
      fatalError("cell does not exist") }

    let nextIndex = IndexPath(row: currentIndex.row + 1, section: currentIndex.section)
    let isLastField = viewModel.dataSource.fields.count == nextIndex.row

    if isLastField {
      cell.textField.resignFirstResponder()
      if shouldValidateOnLastFieldReturnKeyTap {
        validator.validate(self)
      }
      return true
    }

    guard let nextCell = tableView.cellForRow(at: nextIndex) as? PopFormTableViewCell else {
      fatalError() }

    nextCell.textField.becomeFirstResponder()
    return true
  }
}
aBikis
  • 323
  • 4
  • 16
0

You can following if you specifically want to fetch responder text field. Get the current first responder without using a private API

you can also use following code if you only want to dismiss active text field keyboard-

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
   [textField resignFirstResponder];
   return YES;
 }
Community
  • 1
  • 1
rishi
  • 11,779
  • 4
  • 40
  • 59
  • refer following for text view- http://stackoverflow.com/questions/703754/how-to-dismiss-keyboard-for-uitextview-with-return-key – rishi Jan 22 '12 at 15:47