How to dismiss keyboard when touching anywhere outside UITextField (in swift)?
Edited for Swift 4
Edit: Added @objc
. While this isn't the best option for performance, one instance of it here shouldn't cause too many problems until there is a better solution.
Edited to fix when needing to interact with items behind GestureRecognizer.
Edit: Thanks @Rao for pointing this out. Added tap.cancelsTouchesInView = false
.
This should help you with having multiple UITextView
or UITextField
Create an extension of the view controller. This has worked much smoother for me and with less hassle than trying to use .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)
}
}
Call self.setupToHideKeyboardOnTapOnView()
in the viewDidLoad
How to dismiss keyboard when touch outside the textfield?
Try bellow code it hides the keyboard when user touches the view of uiviewcontroller, the code is in swift 3.0, hope it helps you.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true) //This will hide the keyboard
}
Or else you have to set uitapgesturerecognizer for that specific view, or you can make that view uicontrol and set touchupinside event,
All you have to do is call self.view.endEditing(true) from any of above thing.
Close iOS Keyboard by touching anywhere using Swift
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
iOS - Dismiss keyboard when touching outside of UITextField
You'll need to add an UITapGestureRecogniser
and assign it to the view, and then call resign first responder on the UITextField
on it's selector.
The code:
In viewDidLoad
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
In dismissKeyboard:
-(void)dismissKeyboard
{
[aTextField resignFirstResponder];
}
(Where aTextField
is the textfield that is responsible for the keyboard)
Swift 3 version looks like that
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)
For dismissKeyboard
@objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
aTextField.resignFirstResponder()
}
Dismiss keyboard on touch anywhere outside UITextField
Your view hierarchy lives inside a UIWindow
. The UIWindow
is responsible for forwarding touch events to the correct view in its sendEvent:
method. Let's make a subclass of UIWindow
to override sendEvent:
.
@interface MyWindow : UIWindow
@end
The window will need a reference to the current first responder, if there is one. You might decide to also use UITextView
, so we'll observe notifications from both text fields and text views.
@implementation MyWindow {
UIView *currentFirstResponder_;
}
- (void)startObservingFirstResponder {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(observeBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil];
[center addObserver:self selector:@selector(observeEndEditing:) name:UITextFieldTextDidEndEditingNotification object:nil];
[center addObserver:self selector:@selector(observeBeginEditing:) name:UITextViewTextDidBeginEditingNotification object:nil];
[center addObserver:self selector:@selector(observeEndEditing:) name:UITextViewTextDidEndEditingNotification object:nil];
}
- (void)stopObservingFirstResponder {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:UITextFieldTextDidBeginEditingNotification object:nil];
[center removeObserver:self name:UITextFieldTextDidEndEditingNotification object:nil];
[center removeObserver:self name:UITextViewTextDidBeginEditingNotification object:nil];
[center removeObserver:self name:UITextViewTextDidEndEditingNotification object:nil];
}
- (void)observeBeginEditing:(NSNotification *)note {
currentFirstResponder_ = note.object;
}
- (void)observeEndEditing:(NSNotification *)note {
if (currentFirstResponder_ == note.object) {
currentFirstResponder_ = nil;
}
}
The window will start observing the notifications when it's initialized, and stop when it's deallocated:
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self commonInit];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
[self commonInit];
}
return self;
}
- (void)commonInit {
[self startObservingFirstResponder];
}
- (void)dealloc {
[self stopObservingFirstResponder];
}
We'll override sendEvent:
to “adjust” the first responder based on the event, and then call super's sendEvent:
to send the event normally.
- (void)sendEvent:(UIEvent *)event {
[self adjustFirstResponderForEvent:event];
[super sendEvent:event];
}
We don't need to do anything about the first responder if there is no first responder. If there is a first responder, and it contains a touch, we don't want to force it to resign. (Remember, there can be multiple touches simultaneously!) If there is a first responder, and a new touch appears in another view that can become the first responder, the system will handle that correctly automatically, so we also want to ignore that case. But if there is a first responder, and it doesn't contain any touches, and a new touch appears in a view that can't become first responder, we want to make the first responder resign.
- (void)adjustFirstResponderForEvent:(UIEvent *)event {
if (currentFirstResponder_
&& ![self eventContainsTouchInFirstResponder:event]
&& [self eventContainsNewTouchInNonresponder:event]) {
[currentFirstResponder_ resignFirstResponder];
}
}
Reporting whether an event contains a touch in the first responder is easy:
- (BOOL)eventContainsTouchInFirstResponder:(UIEvent *)event {
for (UITouch *touch in [event touchesForWindow:self]) {
if (touch.view == currentFirstResponder_)
return YES;
}
return NO;
}
Reporting whether an event contains a new touch in a view that can't become first responder is almost as easy:
- (BOOL)eventContainsNewTouchInNonresponder:(UIEvent *)event {
for (UITouch *touch in [event touchesForWindow:self]) {
if (touch.phase == UITouchPhaseBegan && ![touch.view canBecomeFirstResponder])
return YES;
}
return NO;
}
@end
Once you've implemented this class, you need to change your app to use it instead of UIWindow
.
If you're creating your UIWindow
in application:didFinishLaunchingWithOptions:
, you need to #import "MyWindow.h"
at the top of your AppDelegate.m
, and then change application:didFinishLaunchingWithOptions:
to create a MyWindow
instead of a UIWindow
.
If you're creating your UIWindow
in a nib, you need to set the custom class of the window to MyWindow
in the nib.
Swift: Can't get UITextField to dismiss keyboard
You need to call resignFirstResponder
inside textFieldShouldReturn
method instead of calling textFieldDidEndEditing
.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
Also in your TapGesture
method simply call endEditing(_:)
with your view
instead of looping through the array of textFields.
func dismiss(_ sender:UITapGestureRecognizer) {
self.view.endEditing(true)
}
Dismiss keyboard when touching outside of UITextField in iwatch
You can achieve this by calling touch view delegate method provided as below.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if (![[touch view] isKindOfClass:[UITextField class]]) {
[self.view endEditing:YES];
}
[super touchesBegan:touches withEvent:event];
}
Let me know in case of any concern.
Related Topics
React Native Change Default iOS Simulator Device
How to Manage Sessions with Afnetworking
iOS 8 - Screen Blank After Dismissing View Controller with Custom Presentation
Flutter: How to Create a New Project
How to Write Init Methods of a Uiviewcontroller in Swift
Load Image from Bundle with iOS
Warning: Attempt to Present Viewcontroller Whose View Is Not in the Window Hierarchy
Why the Extension Is "Momd" But Not "Xcdatamodel" When Search the Path for the Model File
How to Get the Status Bar Height in iOS 13
iPad Multitasking Support Requires These Orientations
Uiimageview Aspect Fit and Center
How to Ask User for Camera Access After They Have Already Denied It on iOS
Color in Storyboard Not Matching Uicolor
How to Change Navigation Bar Color in iOS 7 or 6
A Launch Storyboard or Xib Must Be Provided Unless the App Requires Full Screen
Scnbox Different Colour or Texture on Each Face
How to Properly Change My Status Bar Style in Swift 2/ iOS 9