I have a couple textViews in one cell in a table view controller and I am trying to dismiss the keyboard when you touch anywhere outside the keyboard. I've tried the touches began method but it didn't work. The text views are not transparent and have user interaction enabled.
class RegisterTableViewController: UITableViewController {
override func viewDidLoad() {
// set all text views delegate to self
}
// dismiss keyboard on touch
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touch")
super.touchesBegan(touches, with: event)
view.endEditing(true)
}
}
extension RegisterTableViewController: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
textView.text = ""
}
}
I'm new to swift and would appreciate any help!
Add touchesBegan code in your UITableViewCell file , which will work if you touch outside TextField but inside cell
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.Your_TextField.endEditing(true)
}
But it won't work outside cell (In UIVIew of another ViewController) , so add UITapGesture to achieve that
override func viewDidLoad() {
super.viewDidLoad()
let tapgest = UITapGestureRecognizer(target: self, action: #selector(taptoend))
self.Your_Table_View.addGestureRecognizer(tapgest)
}
#objc func taptoend()
{
self.Your_Table_View.endEditing(true)
print("Key-Board will be dismissed here")
}
You need to add Tap gesture recognizer inside your cell. Place all you text inputs in a UIView. make outlet of UIView inside cell. and than add this code in your cell.
#IBOutlet weak var myView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let tap = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard))
self.myView.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
self.endEditing(true)
}
I have created a custom control for Uber like OTP TextField. I want to consume the touch in my control and not let it propagate through the UIResponder Chain. So I have overridden the methods as described in apple documentation.
extension BVAPasswordTextField {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
becomeFirstResponder()
}
override func touchesMoved(Set<UITouch>, with: UIEvent?) {
}
override func touchesEnded(Set<UITouch>, with: UIEvent?) {
}
override func touchesCancelled(Set<UITouch>, with: UIEvent?) {
}
override func touchesEstimatedPropertiesUpdated(Set<UITouch>) {
}
}
Now in some view controller I want to dismiss the keyboard when the user taps anywhere outside my custom control.
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureRecogniser = UITapGestureRecognizer(target: self, action: #selector(ViewController.backgroundTapped))
tapGestureRecogniser.numberOfTapsRequired = 1
view.addGestureRecognizer(tapGestureRecogniser)
// Do any additional setup after loading the view, typically from a nib.
}
#objc func backgroundTapped() {
self.view.endEditing(true)
}
But whenever I tap on the textfield backgroundTapped also gets called.
Note:- It is a control where based on enum values you can create different UI Components for taking input. So this control can be shared among the whole team... I won't be the only guy using it.... So I want it to behave exactly like UITextfield in touch scenario
You can handle the tap gesture using UITapGestureRecognizerDelegate. It allows you to decide whether or not gesture should begin. In your case, it should be done basing on the location of the touch.
extension ViewController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let location = gestureRecognizer.location(in: self.view)
// return true is location of touch is outside our textField
return !textField.frame.contains(location)
}
}
Just make sure you've set a delegate for your gesture at viewDidLoad
tapGestureRecogniser.delegate = self
UPDATE
If I got your setup right, you have a view and some subviews that are used for input. And you want to resignFirstResponder when this super-view is touched. In that case you can use gestureRecognizerShouldBegin like that
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let location = gestureRecognizer.location(in: self.view)
for subview in self.view.subviews {
if subview.frame.contains(location) {
return false
}
}
return true
}
In my opinion, if you want to handle some view interaction in a specific way, you need to do it using that specific view. And what you're doing now feels like trying to change behavior on one view, using another view.
I have an UIView (from UIViewController) that receive touch and remove keyboard. In the same screen I've a UIButton that show the password, when I touch in UIButton the touch goes to UIView and remove keyboard.
How prevent the UIView to receive touch from UIButton?
I'd try .isExclusiveTouch but didn't work.
EDIT
My extension that remove the keyboard:
import UIKit
public extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(
target: self,
action: #selector(UIViewController.dismissKeyboard)
)
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
}
In my ViewController, the button:
self.myButton.addTarget(self, action: #selector(self.myButtonHandler), for: .touchUpInside)
self.view.addSubview(self.myButton)
Don't use gestures just use this code
override func touchesBegan(_ touches: Set<UITouch>, with event:UIEvent?) {
if let touch = touches.first {
view.endEditing(true)
}
super.touchesBegan(touches, with: event)
}
Here when you touch any part of view (not buttons) keyboard will be dismissed by code (view.endEditing(true))
Try setting userIntrecationEnabled to false.
//example
yourView.isUserInteractionEnabled = false
If user interaction is disabled for a view, it will ignore touches.
I have this Setup in my Storyboard.
In my first ViewController Scene I have a MapView from MapBox. In there I have put a TextField (AddressTextField). On that TextField when touching the view, i'm running self.addressTextField.resignFirstResponder(), but after that neither the mapview, nor any other element in there or in the Embedded Segues react on a touch or click. Probably this is because I didn't completely understand the system of the First Responder. I'm thankful for every help.
Edit 1:
I think I know what's going on now, but I don't know how to fix it. When I add the Gesture Recognizer to the View (or to the mapView, that doesn't matter), the other UIViews and the MapView do not recognize my Tap-Gestures anymore. When I am not adding the Recognizer everything works fine. It seems as if the Gesture Recognizer is recognizing every tap I make on either the UIViews or the MapView and therefore other gestures are not recognized.
Edit 2:
I just added a print() to dismissKeyboard(). As soon as any Touch Event gets recognized on the MapView or the other UIViews, dismissKeyboard() gets called. So I think my thought of Edit 1 was correct. Does anyone know how I can solve this, so that it's not only dismissKeyboard() that gets called ?
Some Code:
func dismissKeyboard(){
self.addressTextField.resignFirstResponder()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
dismissKeyboard()
return true
}
//Class (only partially)
class ViewController: UIViewController, MGLMapViewDelegate, CLLocationManagerDelegate, UITextFieldDelegate {
override func viewDidLoad(){
mapView.delegate = self
addressTextField.delegate = self
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
self.mapView.addGestureRecognizer(tap)
}
}
Others are just #IBActions linked to the Buttons, or other elements.
try this:
func dismissKeyboard(){
view.endEditing(true)
}
hope it helps!
After I knew the real issue I was able to solve the problem. I declared a var keyboardEnabled. Then I added these lines to my class.
class ViewController: UIViewController, UIGestureRecognizerDelegate {
var keyboardEnabled = false
override func viewDidLoad(){
super.viewDidLoad()
//Looks for single tap
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
self.mapView.addGestureRecognizer(tap)
}
/* Setting keyboardEnabled */
//Editing Target did end
#IBAction func editingTargetDidEnd(_ sender: Any) {
keyboardEnabled = false
}
//Editing TextField Started
#IBAction func editingAdressBegin(_ sender: Any) {
keyboardEnabled = true
}
//Call this function when the tap is recognized.
func dismissKeyboard() {
self.mapView.endEditing(true)
keyboardEnabled = false
}
//Implementing the delegate method, so that I can add a statement
//decide when the gesture should be recognized or not
//Delegate Method of UITapGestureRecognizer
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return keyboardEnabled
}
}
With this solution keyboardEnabled takes care of deciding wether my UIGestureRecognizer should react or not. If the Recognizer doesn't react, the Gesture is simply passed on to the UIViews or other Elements that are in my MapView.
Thanks for all your answers!
I have been looking all over for this but I can't seem to find it. I know how to dismiss the keyboard using Objective-C but I have no idea how to do that using Swift? Does anyone know?
override func viewDidLoad() {
super.viewDidLoad()
//Looks for single or multiple taps.
let tap = UITapGestureRecognizer(target: self, action: #selector(UIInputViewController.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)
}
Here is another way to do this task if you are going to use this functionality in multiple UIViewControllers:
// Put this piece of code anywhere you like
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
}
Now in every UIViewController, all you have to do is call this function:
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
This function is included as a standard function in my repo which contains a lot of useful Swift Extensions like this one, check it out: https://github.com/goktugyil/EZSwiftExtensions
An answer to your question on how to dismiss the keyboard in Xcode 6.1 using Swift below:
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)
}
}
(Source of this information).
Swift 4 working
Create extension as below & call hideKeyboardWhenTappedAround() in your Base view controller.
//
// 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)
}
}
Most important thing to call in your Base View Controller so that no need to call all time in all view controllers.
You can call
resignFirstResponder()
on any instance of a UIResponder, such as a UITextField. If you call it on the view that is currently causing the keyboard to be displayed then the keyboard will dismiss.
swift 5 just two lines is enough. Add into your viewDidLoad should work.
let tapGesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
view.addGestureRecognizer(tapGesture)
If your tap gesture blocked some other touches, then add this line:
tapGesture.cancelsTouchesInView = false
for Swift 3 it is very simple
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
if you want to hide keyboard on pressing RETURN key
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
but in second case you will also need to pass delegate from all textFields to the ViewController in the Main.Storyboard
//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
}
}
Swift 3:
Easiest way to dismiss 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
}
In swift you can use
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
view.endEditing(true)
}
Just one line of code in viewDidLoad() method:
view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
Dash's answer is correct and preferred. A more "scorched earth" approach is to call view.endEditing(true). This causes view and all its subviews to resignFirstResponder. If you don't have a reference to the view you'd like to dismiss, this is a hacky but effective solution.
Note that personally I think you should have a reference to the view you'd like to have resign first responder. .endEditing(force: Bool) is a barbaric approach; please don't use it.
I found the best solution included the accepted answer from #Esqarrouth, with some adjustments:
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboardView")
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
func dismissKeyboardView() {
view.endEditing(true)
}
}
The line tap.cancelsTouchesInView = false was critical: it ensures that the UITapGestureRecognizer does not prevent other elements on the view from receiving user interaction.
The method dismissKeyboard() was changed to the slightly less elegant dismissKeyboardView(). This is because in my project's fairly old codebase, there were numerous times where dismissKeyboard() was already used (I imagine this is not uncommon), causing compiler issues.
Then, as above, this behaviour can be enabled in individual View Controllers:
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
In storyboard:
select the TableView
from the the right-hand-side, select the attribute inspector
in the keyboard section - select the dismiss mode you want
Swift 3:
Extension with Selector as parameter to be able to do additional stuff in the dismiss function and cancelsTouchesInView to prevent distortion with touches on other elements of the view.
extension UIViewController {
func hideKeyboardOnTap(_ selector: Selector) {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: selector)
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
}
Usage:
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardOnTap(#selector(self.dismissKeyboard))
}
func dismissKeyboard() {
view.endEditing(true)
// do aditional stuff
}
I have use IQKeyBoardManagerSwift for keyboard. it is easy to use.
just Add pod 'IQKeyboardManagerSwift'
Import IQKeyboardManagerSwift and write code on didFinishLaunchingWithOptions in AppDelegate.
///add this line
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
IQKeyboardManager.shared.enable = true
To expand on Esqarrouth's answer, I always use the following to dismiss the keyboard, especially if the class from which I am dismissing the keyboard does not have a view property and/or is not a subclass of UIView.
UIApplication.shared.keyWindow?.endEditing(true)
And, for convenience, the following extension to the UIApplcation class:
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)
}
}
Use IQKeyboardmanager that will help you solve easy.....
/////////////////////////////////////////
![ how to disable the 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)
}
}
If you use a scroll view, It could be much simpler.
Just select Dismiss interactively in storyboard.
Add this extension to your 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)
}
}
In Swift 4, add #objc:
In the viewDidLoad:
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard))
view.addGestureRecognizer(tap)
Function:
#objc func dismissKeyboard() {
view.endEditing(true)
}
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)
}
}
As a novice programmer it can be confusing when people produce more skilled and unnecessary responses...You do not have to do any of the complicated stuff shown above!...
Here is the simplest option...In the case your keyboard appears in response to the textfield - Inside your touch screen function just add the resignFirstResponder function. As shown below - the keyboard will close because the First Responder is released (exiting the Responder chain)...
override func touchesBegan(_: Set<UITouch>, with: UIEvent?){
MyTextField.resignFirstResponder()
}
This one liner resigns Keyboard from all(any) the UITextField in a UIView
self.view.endEditing(true)
Posting as a new answer since my edit of #King-Wizard's answer was rejected.
Make your class a delegate of the UITextField and override touchesBegan.
Swift 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)
}
}
For Swift3
Register an event recogniser in viewDidLoad
let tap = UITapGestureRecognizer(target: self, action: #selector(hideKeyBoard))
then we need to add the gesture into the view in same viewDidLoad.
self.view.addGestureRecognizer(tap)
Then we need to initialise the registered method
func hideKeyBoard(sender: UITapGestureRecognizer? = nil){
view.endEditing(true)
}
Here is how to dismiss the keyboard by tapping anywhere else, in 2 lines using Swift 5.
(I hate to add another answer, but since this is the top result on Google I will to help rookies like me.)
In your ViewController.swift, find the viewDidLoad() function.
Add these 2 lines:
let tap: UIGestureRecognizer = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing))
view.addGestureRecognizer(tap)
You can also add a tap gesture recognizer to resign the 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")
}
Another possibility is to simply add a big button with no content that lies underneath all views you might need to touch.
Give it an action named:
#IBAction func dismissKeyboardButton(sender: AnyObject) {
view.endEditing(true)
}
The problem with a gesture recognizer was for me, that it also caught all touches I wanted to receive by the tableViewCells.
If you have other views that should receive the touch as well you have to set
cancelsTouchesInView = false
Like this:
let elsewhereTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
elsewhereTap.cancelsTouchesInView = false
self.view.addGestureRecognizer(elsewhereTap)
override func viewDidLoad() {
super.viewDidLoad()
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap)))
}
func tap(sender: UITapGestureRecognizer){
print("tapped")
view.endEditing(true)
}
Try this,It's Working