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
}
Related
I have UIViewController with UITextfield and several other elements (several subviews and buttons). I want to close the keyboard when tapped somewhere outside of the UITextfield.
I know there is an answer Close iOS Keyboard by touching anywhere using Swift, but this way doesn't work if user taps on viewController's subviews or buttons.
I can add the similar UITapGestureRecognizer for each subViews and buttons, but is there a smarter way to resolve this?
extension UIViewController{
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
Also if you have elements in a UIScrollView, add this method too:
extension UIScrollView {
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.next?.touchesBegan(touches, with: event)
}
}
In code, I can use this below method to let vc's view becomeFirstResponder, and play down the show-up keyboard.
the code is below:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
Could I set this function in my storyboard? or there is some way easier for self.view.endEditing(true) when click self.view?
Because if not do this, I will copy the function upper to almost every vc.
Just put this somewhere in the code and it would resolve your issue with code duplicating
extension UIViewController {
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
self.view.endEditing(true)
}
}
I'm not sure tho if it's a good way of doing this, maybe you'd like to rethink the architectural issues of resigning the textfield's responder, regards of what you really need.
You can create an extension of UIViewController and then make swizzling methods for touchesBegans and your own customTouchBegans. see an example of swizzling methods for viewWillAppear
https://www.uraimo.com/2015/10/23/effective-method-swizzling-with-swift/
I have multiple textFields in different viewControllers where keyboard is popped up.
I know how to dismiss keyboard when user clicks on a different part of the screen but I don't want to go and hard code it into every corner of my app.
So is there anyway to enforce keyboard getting keyboard dismissed everywhere on the app when the user clicks anywhere on the screen other than keyboard?
I was thinking of extending the UIViewController, but I also have some textFields inside a view that I add as a subview. Perhaps there could be someway that I extend TextField class itself?
I suggest to create a base UIViewController and let each of your ViewControllers inherit it; override touchesBegan method in it:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
view.endEditing(true)
}
OR you can override viewDidLoad -in the base ViewController- and add a UITapGestureRecognizer to the view, as follows:
override func viewDidLoad() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(Base.endEditing))
view.addGestureRecognizer(tapGesture)
}
func endEditing() {
view.endEditing(true)
}
You can also use an extension of a view controller, if you want the keyboard dismissal to apply to all of them:
extension UIViewController {
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(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 used following code to remove keyborad
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.view.endEditing(true)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
however it will work fine when i click any where in the screen but when i click on button(UIBUTTON) which is present in my screen the keyboard in not hide until i press return Key or touch anywhere in UIView
please help me
Did you test to put textField.resignFirstResponder() in the button's function?
Ex :
#IBAction func btn(sender: AnyObject) {
textField.resignFirstResponder()
}
A more general solution would be to use:
self.view.endEditing(true)