tap on UITextField not working - ios

I read a lot try to find a way to handle uitextfield click but nothing working for me
What I want:
I want add tap on UITextField and open dialog
What I tried:
class CreateMessagesViewController: UIViewController {
#IBOutlet weak var testField: UITextField!
#IBOutlet weak var testView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
// testField.addGestureRecognizer(tap)
testView.addGestureRecognizer(tap)
testField.addTarget(self, action: #selector(onTapped(_:)), for: .touchDown)
}
func onTapped(_ sender : UITextField){
print("Hello World")
}
func handleTap(_ sender: UITapGestureRecognizer) {
print("Hello World")
}
}
As you can see I tried 2 ways:
UITapGestureRecognizer
selector
Just for the test I add simple UIView to make sure tap is working and it worked.
Why it doesn't work on uiTextField? Is there anything I have missed?

Instead of adding gesture recognizer you can write the code for opening dialog in
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool{
openDialog()//Function which will open the dialog
return false
}
I think it should have the same effect as you want.

1)add gesture recognizer:
let tapGR = UITapGestureRecognizer(target: self, action: #selector(someFunc))
tapGR.delegate = self
textField.addGestureRecognizer(tapGR)
2)make sure that you allow your tap handler when it is necessary:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true //or add your custom check here if you need
}
Without of the second part you get a buggy textField where sometimes tap gesture doesn't work, sometimes default gestures not handled!

There is a simpler way to achieve this. You should conform your view controller class to UITextFieldDelegate and implement textFieldDidBeginEditingin your class.
func textFieldDidBeginEditing(_ textField: UITextField){
//show popup here
}
If you are having multiple text fields, assign a tag to your text field in the storyboard(or in the code) to recognize the text field.
func textFieldDidBeginEditing(_ textField: UITextField){
// check your tag here
if textField.tag == 0 {
//show your popup here
}
}

Add GestureRecognizer to UITextField superview and check if help:
testField.superview.addGestureRecognizer(tap)

I created sample one for your question both Swift and Objective C but it not working.I used the Tap Gesture recognizer code for textField but it not even called.
Not Worked below Code in Swift and Objective C
Swift
let tap = UITapGestureRecognizer(target: self,action: #selector(handleTaponTextField(_:)))
tap.numberOfTapsRequired = 1
tap.delegate = self
txtFldTapMe.isUserInteractionEnabled = true
txtFldTapMe.addGestureRecognizer(tap)
func handleTaponTextField(_ sender: UITapGestureRecognizer)
{
print("Tap is handled here!")
}
Objective C
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.delegate = self;
txtfldTapME.userInteractionEnabled = YES;
[txtfldTapME addGestureRecognizer:tapGesture];
func handleTaponTextField(_ sender: UITapGestureRecognizer)
{
print("Tap is handled here!")
}
Then I tried with below addTarget action method for textField and it works fine.
Worked below Code in Swift and Objective C
Swift
txtFldTapMe.addTarget(self, action: #selector(textFieldEditDidBegin(_:)), for: .editingDidBegin)
func textFieldEditDidBegin(_ textField: UITextField) {
print("Text editing begin here!")
}
See the methods
You should use above methods of textField
Objective C
[txtfldTapME addTarget:self action:#selector(editingDidBeginStarted:) forControlEvents: UIControlEventEditingDidBegin];
-(void)editingDidBeginStarted:(UITapGestureRecognizer *)sender{
NSLog(#"Editing started here");
}
See the below textField methods

Try below code
yourTextField.addTarget(self, action: #selector(didChangeText), for: .editingChanged)
addSubview(view)
#objc func didChangeText(textField:UITextField) {
let str = textField.text
//your functionality here
}

It's not possible. Because Textfield delegate method call.

Related

UITapGestureRecognizer is not invoked when I clicked button with IBAction

I have UITextField and UIButton in my application.
To hide system keyboard which is shown when UITextField is clicked, I added UITapGestureRecognizer to my view.
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(didTap(_:)))
view.addGestureRecognizer(tapGesture)
}
#objc func didTap(_ recognizer: UIGestureRecognizer) {
view.endEditing(true)
}
#IBAction func onClickedButton(_ sender: Any) {
print("aaa")
}
This code worked very well when I touched outside of my button.
However, when I clicked the button which has IBAction(onClickedButton), the keyboard did not disappear and only the message "aaa" printed in output console.
What I want to do is to hide keyboard and invoke IBAction at the same time. In other words, I want to invoke Tap gesture and IBAction at the same time, when I clicked my button.
How can I acheive this?
I found the solution.
Just setting
tapGesture.cancelsTouchesInView = false
can acheive this.
By doing like this, tapGesture hides keyboard and after that, passes touch event to the UIButton.
You can just add view.endEditing(true) to your onClickedButton.
try this
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(didTap(_:)))
view.addGestureRecognizer(tapGesture)
}
#objc func didTap(_ recognizer: UIGestureRecognizer) {
view.endEditing(true)
}
#IBAction func onClickedButton(_ sender: Any) {
print("aaa")
view.endEditing(true)
}
}

UILabel set onClick

I'm building an application in Swift 3, so I want to call a function if I click on a particular UILabel, so I'm write this code but not works:
let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapFunction))
self.labelTemp.isUserInteractionEnabled = true
self.labelTemp.addGestureRecognizer(tap)
How can I render UILabel clickable ?
Set user interaction enabled for the UILabel and add the below code in the viewDidLoad()
self.label.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(self.labelTapped))
self.label.addGestureRecognizer(tap)
Add the tap action function as below :
#objc func labelTapped(_ gestureRecognizer: UITapGestureRecognizer) {
print("Label clicked")
}
Please make user that there is no other transparent view overlapping the UILabel in the view. If the UILabel is a part of another view then please make sure that the container View's user interaction is enabled.
Hope this helps.
Your selector should be an #objc func within self.
<#YourLabel#>.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.handleLabelTap)))
And when the user taps the label it will trigger:
#objc func handleLabelTap() {
// handle label tap here
}
You are lacking a function to trigger when the gesture touch is recognized. You need to add following:
let tap = UITapGestureRecognizer(target: self, action: #selector(tapFunction(_:)))
self.labelTemp.isUserInteractionEnabled = true
self.labelTemp.addGestureRecognizer(tap)
#objc func tapFunction(_ gestureRecognizer: UITapGestureRecognizer) {
// handle label tap here
}
Please ensure that You have connected the outlet to UILabel because I have created simple demo code by copy-paste your code and it is worked as expected.
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(tapFunction))
self.labelTemp.isUserInteractionEnabled = true
self.labelTemp.addGestureRecognizer(tap)
}
#objc func tapFunction() {
print("tapFunction")
}
I suggest, Please remove UILabel from UIViewController and add it again.
Download sample code
Note: - Please ensure that user-interaction of UILabelis enabled
First you need to add Tap Gesture into storyboard
Create Action of that particular gesture
override func viewDidLoad() {
super.viewDidLoad()
let tapOnLabel = UITapGestureRecognizer(target: self, action: #selector(self.tapGestireAction))
self.labelTemp.isUserInteractionEnabled = true
self.labelTemp.addGestureRecognizer(tapOnLabel)
}
#IBAction func tapGestureAction(_ sender: UITapGestureRecognizer) {
//Perform action
}

GestureRecognizer taking all Touch Input

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!

Ios Swift Override double tap of UItextField

I want to write a custom code on double tap on UITextField and block the default text editing and popup of the keyboard. I've tried the following and nothing has worked for me so far. Kindly help me solve this problem.
let gestureArray = NamTxtBoxVal.gestureRecognizers
var tapGesture = UITapGestureRecognizer()
for idxVar in gestureArray!
{
if let tapVar = idxVar as? UITapGestureRecognizer
{
if tapVar.numberOfTapsRequired == 2
{
tapGesture = tapVar
NamTxtBoxVal.removeGestureRecognizer(tapGesture)
}
}
}
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(namFnc(_:)))
doubleTap.numberOfTapsRequired = 2
doubleTap.delegate = self
tapGesture.requireGestureRecognizerToFail(doubleTap)
NamTxtBoxVal.addGestureRecognizer(doubleTap)
I've also tried:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool
{
return false
}
The only way I know of for you to do this is to
put a UIView behind the UITextField
set the textField's userInteractionEnabled = false
add the double tap gesture to the UIView
This will allow you to register a double tap on the TextField area and not popup any keyboard or enter editing mode.
Not sure what you plan on doing with the textField after double tap but you should be able to handle most stuff programmatically at this point.
Code for this is:
class ViewController: UIViewController {
#IBOutlet weak var myViewBehindMyTextField: UIView!
#IBOutlet weak var myTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.myTextFieldTapped(_:)))
tapGesture.numberOfTapsRequired = 2
myViewBehindMyTextField.addGestureRecognizer(tapGesture)
}
func myTextFieldTapped(sender: UITapGestureRecognizer) {
print("Double tapped on textField")
}
}

UIButton with single press and long press events swift

I want to trigger two action on button click and button long click. I have add a UIbutton in my interface builder. How can i trigger two action using IBAction can somebody tell me how to archive this ?
this is the code i have used for a button click
#IBAction func buttonPressed (sender: UIButton) {
....
}
can i use this method or do i have to use another method for long click ?
If you want to perform any action with single tap you and long press the you can add gestures into button this way:
#IBOutlet weak var btn: UIButton!
override func viewDidLoad() {
let tapGesture = UITapGestureRecognizer(target: self, #selector (tap)) //Tap function will call when user tap on button
let longGesture = UILongPressGestureRecognizer(target: self, #selector(long)) //Long function will call when user long press on button.
tapGesture.numberOfTapsRequired = 1
btn.addGestureRecognizer(tapGesture)
btn.addGestureRecognizer(longGesture)
}
#objc func tap() {
print("Tap happend")
}
#objc func long() {
print("Long press")
}
This way you can add multiple method for single button and you just need Outlet for that button for that..
#IBOutlet weak var countButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
addLongPressGesture()
}
#IBAction func countAction(_ sender: UIButton) {
print("Single Tap")
}
#objc func longPress(gesture: UILongPressGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
func addLongPressGesture(){
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(gesture:)))
longPress.minimumPressDuration = 1.5
self.countButton.addGestureRecognizer(longPress)
}
Why not create a custom UIButton class, create a protocol and let the button send back the info to delegte. Something like this:
//create your button using a factory (it'll be easier of course)
//For example you could have a variable in the custom class to have a unique identifier, or just use the tag property)
func createButtonWithInfo(buttonInfo: [String: Any]) -> CustomUIButton {
let button = UIButton(type: .custom)
button.tapDelegate = self
/*
Add gesture recognizers to the button as well as any other info in the buttonInfo
*/
return button
}
func buttonDelegateReceivedTapGestureRecognizerFrom(button: CustomUIButton){
//Whatever you want to do
}

Resources