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 want to get all touches and buttons actions count in my app to show in UI like how many actions done sofar by user. It's a Swift app.
I tried with following code:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
UtilityClass.sharedInstance.touchesCount += 1
print(UtilityClass.sharedInstance.touchesCount)
}
But it's calling only UIView touches events, but not calling for UIButton actions, is there any other solutions to achieve my requirement.
If its single button action, I can call this integer to increase, but, I have number of button actions in my app, thats why I am posting this here.
Try add this to your project
extension UIButton {
open override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
super.sendAction(action, to: target, for: event)
UtilityClass.sharedInstance.touchesCount += 1
print(UtilityClass.sharedInstance.touchesCount)
}
}
edit:
class ViewController: UIViewController {
#IBAction func buttonAction(_ sender: Any) {
}
}
extension UIButton {
open override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
super.sendAction(action, to: target, for: event)
print("1111")
}
}
above is my full test code, I have a outlet button which is UIButton, every time I click the button action, it will print 1111, and if your button class is custom subclass of UIButton, please change extension UIButton { to extension YourCustomButtonName {
I'm new to Swift, and I was recently learning about UITextField and how it delegates. I was wondering if there was a simple way to dismiss the keyboard when taping outside of it (somewhere else in the view). Currently, I am using UITapGestureRecognizer to do this. It works, but I was wondering if there was a simpler way to do it.
You can use this method to dismiss the keyboard by tapping anywhere on the screen
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
But be sure to set the delegates beforehand.
Set the delegate of UITextField, Like as UITableviewDataSource,Delegate. Write yourTextFieldDelegate.delegate = self in viewDidLoad()
Then, write this function:
func textFieldShouldReturn(textField: UITextField) -> Bool {
titleTextField.resignFirstResponder()
return true
}
This question already has answers here:
How do you make a UITextView detect link part in the text and still have userInteractionDisabled?
(4 answers)
Closed 4 years ago.
I have been struggling to detect a tap on a UITextView with Swift.
My UITextViews are in a table, I must be able to detect links and press them, those links length are unknown.
Also if I tap on the cell, that I don't tap on a link, I want push a new UIViewController on my navigation controller stack.
I tried to create my own textview to overwrite the touchesCancelled, but it wasn't a success. It detects the cancellation which isn't considered a tap on the real device.
The bug doesn't occur in the simulator, but it seems I can't tap on the real device, only long press will work.
class LinkTextView: UITextView {
override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
self.textViewWasTapped(self)
}
}
I tried adding directly a gesture recognizer. I didn't have any success there either. It doesn't call the gesture recognizer at all.
I added the UIGestureReconizer delegate to my UIViewController and those lines in my
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var singleTap : UIGestureRecognizer = UIGestureRecognizer(target: self, action: "tapTextView:")
singleTap.delegate = self
cell.mTextOutlet.attributedText = myMutableString
cell.mTextOutlet.addGestureRecognizer(singleTap)
In my LinkTextView class :
class LinkTextView: UITextView {
func tapTextView(stapGesture: UIGestureRecognizer){
println("TAPPING1")
}
}
I looked the forums and found this post : post. It suggests to use CHHLinkTextView. I tried to use it but what I want is to detect the link automatically, which normal uitextview actually does.
I did try using the checkBox in interface builder to parse links with the CHHLinkTextView, but it doesn't work. I didn't see anything in the documentation suggesting it could be done.
How should I proceed ?
You're very close with your first attempt in subclassing UITextView, but instead of overriding only touchesCancelled, you'll want to override all of the touches* methods, i.e.
touchesBegan
touchesMoved
touchesEnded
touchesCancelled
In the overridden methods, send the touch down the responder chain by getting the textView's nextResponder(), check that it isn't nil, and call the method on the next responder.
The reason this works is because the UITextView will intercept the touch if it's on a URL and the UIResponder methods will never be called -- try it for yourself by implementing textView:shouldInteractWithURL:inRange in your tableViewCell or wherever, and you'll see that it's called before any touch events are passed along.
This should be the minimum for what you're trying to do (it's repetitive but short):
class PassThroughTextView: UITextView {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let next = next {
next.touchesBegan(touches, with: event)
} else {
super.touchesBegan(touches, with: event)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let next = next {
next.touchesEnded(touches, with: event)
} else {
super.touchesEnded(touches, with: event)
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
if let next = next {
next.touchesCancelled(touches, with: event)
} else {
super.touchesCancelled(touches, with: event)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let next = next {
next.touchesMoved(touches, with: event)
} else {
super.touchesMoved(touches, with: event)
}
}
}
// In case you want to do anything with the URL or textView in your tableViewCell...
class TableViewCell: UITableViewCell, UITextViewDelegate {
#IBOutlet var textView: PassThroughTextView!
func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
println("textView shouldInteractWithURL")
return true
}
}
I did as Ralfonso said without success, but it helped me realize I had a gesture recognizer conflict. Turns out I didn't have to override all 4 methods of the UITextView, I just override the touchesBegan.
What I was doing in the viewDidLoad was add a gesture recognizer to dismiss the keyboard :
var tapOutTextField: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(tapOutTextField)
What didn't make sense and sent me in a wrong direction was that touchesBegan was actually called after a delay (so was touchCancelled), and I could not get the same behaviour as a UIButton. All that because of this gesture recognizer conflict.
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