38

I would like to detect the touch action on a UITextField.

It seems the "Touch Up Inside" action is not fired by touching inside the textfield.

Jonas Deichelmann
  • 3,513
  • 1
  • 30
  • 45
Daniele B
  • 19,801
  • 29
  • 115
  • 173

12 Answers12

80

It seems "Touch Up Inside" is not enabled for UITextField, but "Touch Down" works.

So the solution is as follows:

Swift 4.x

myTextField.addTarget(self, action: #selector(myTargetFunction), for: .touchDown)
@objc func myTargetFunction(textField: UITextField) {
    print("myTargetFunction")
}

Swift 3.x

myTextField.addTarget(self, action: #selector(myTargetFunction), for: UIControlEvents.touchDown)

@objc func myTargetFunction(textField: UITextField) {
    print("myTargetFunction")
}
Hitesh Surani
  • 12,733
  • 6
  • 54
  • 65
Daniele B
  • 19,801
  • 29
  • 115
  • 173
40

Swift 4 and higher:

class ViewController: UIViewController, UITextFieldDelegate {
    func textFieldDidBeginEditing(_ textField: UITextField) {
        if textField == myTextField {
            print("You edit myTextField")
        }
    }
}

This is a delegate function.

Jonas Deichelmann
  • 3,513
  • 1
  • 30
  • 45
13

here's Swfit:

and you don't need to use the "touchUpInside" just use the delegate methods like so:

Make your View controller a delegate:

class ViewController: UIViewController, UITextFieldDelegate{

func textFieldDidBeginEditing(textField: UITextField) -> Bool {
    if textField == myTextField {
        return true // myTextField was touched
    }
}

Here's the other delegate methods:

protocol UITextFieldDelegate : NSObjectProtocol {

    optional func textFieldShouldBeginEditing(textField: UITextField) -> Bool // return NO to disallow editing.
    optional func textFieldDidBeginEditing(textField: UITextField) // became first responder
    optional func textFieldShouldEndEditing(textField: UITextField) -> Bool // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
    optional func textFieldDidEndEditing(textField: UITextField) // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called

    optional func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool // return NO to not change text

    optional func textFieldShouldClear(textField: UITextField) -> Bool // called when clear button pressed. return NO to ignore (no notifications)
    optional func textFieldShouldReturn(textField: UITextField) -> Bool // called when 'return' key pressed. return NO to ignore.
}

from swift docs:

struct UIControlEvents : RawOptionSetType {
    init(_ rawValue: UInt)
    init(rawValue: UInt)

    static var TouchDown: UIControlEvents { get } // on all touch downs
    static var TouchDownRepeat: UIControlEvents { get } // on multiple touchdowns (tap count > 1)
    static var TouchDragInside: UIControlEvents { get }
    static var TouchDragOutside: UIControlEvents { get }
    static var TouchDragEnter: UIControlEvents { get }
    static var TouchDragExit: UIControlEvents { get }
    static var TouchUpInside: UIControlEvents { get }
    static var TouchUpOutside: UIControlEvents { get }
    static var TouchCancel: UIControlEvents { get }

    static var ValueChanged: UIControlEvents { get } // sliders, etc.

    static var EditingDidBegin: UIControlEvents { get } // UITextField
    static var EditingChanged: UIControlEvents { get }
    static var EditingDidEnd: UIControlEvents { get }
    static var EditingDidEndOnExit: UIControlEvents { get } // 'return key' ending editing

    static var AllTouchEvents: UIControlEvents { get } // for touch events
    static var AllEditingEvents: UIControlEvents { get } // for UITextField
    static var ApplicationReserved: UIControlEvents { get } // range available for application use
    static var SystemReserved: UIControlEvents { get } // range reserved for internal framework use
    static var AllEvents: UIControlEvents { get }
}

UITextField doesn't respond to "touchUpInside" see to the right side, you'll find it's acceptable control events

Larry Pickles
  • 4,615
  • 2
  • 19
  • 36
  • Thanks @Lacerax, but I would like to detect then the user taps the textfield. I am already detecting editing with this function `myTextField.addTarget(self, action: "myTargetFunction:", forControlEvents: UIControlEvents.EditingChanged)`, without the need of a UITextFieldDelegate – Daniele B Aug 28 '15 at 00:03
  • so you mean touch but not enter the textfield, right? – Larry Pickles Aug 28 '15 at 00:04
  • You shoudl read the docs on UITextField, it only responds to these selector methods: UIControlEventEditingDidBegin = 1 << 16, // UITextField UIControlEventEditingChanged = 1 << 17, UIControlEventEditingDidEnd = 1 << 18, UIControlEventEditingDidEndOnExit = 1 << 19, // 'return key' ending editing – Larry Pickles Aug 28 '15 at 00:07
  • touchupinside is NOT one of those – Larry Pickles Aug 28 '15 at 00:08
  • look at the answer in one se – Larry Pickles Aug 28 '15 at 00:08
  • Thanks Larcerax! It seems TouchDown works though! It works in this way: `myTextField.addTarget(self, action: "myTargetFunction:", forControlEvents: UIControlEvents.TouchDown)` – Daniele B Aug 28 '15 at 00:15
  • I am new to iOS/Swift, I wonder if using `myTextField.addTarget` is exactly equivalent to your delegate approach – Daniele B Aug 28 '15 at 00:15
  • yesh, sorry about that, Touch down does work it seems the docs are showing htat, I should have been more clear – Larry Pickles Aug 28 '15 at 00:15
  • Yes, this is how Apple works, the uitextfield is a UIControl delegate which intercepts touch events and stores them in an NSSet – Larry Pickles Aug 28 '15 at 00:16
  • the textfield delegate methods is the equivalent, sort of , of using (sender: blah) with uibutton intercepts, its the same principle – Larry Pickles Aug 28 '15 at 00:17
  • so, isn't it neater to use `addTarget()` instaed of adding the `UITextFieldDelegate` to the class? – Daniele B Aug 28 '15 at 00:17
  • I would say it's neater, but the delegate methods are already set up for easy use, they separate out the NSSet of toucehes for you, per se, so it's easier for you to plan around it, but then again, this "EditingDidEndOnExit" is the same thing as calling the delegate method, but what does this doe for Apple? it's MVC programming, they have a subclass of NSObject which is the UITextfield that is a delegate of UiControl, so it's by design they have this set up this way, the class of UITextField should control it's own actions, not its delegate object, but either way its fine – Larry Pickles Aug 28 '15 at 00:20
  • Also, should you ever want to customize a UITextField and make your own subclass, you can the "control events" to customized what you want to ahve happen given your custom UITextField, this can get very very compplicated, but this is another reason, it's for some very advanced programming – Larry Pickles Aug 28 '15 at 00:21
  • Thanks for your explanations! – Daniele B Aug 28 '15 at 00:22
11

Update For Swift 3

Here is the code for Swift 3:

myTextField.addTarget(self, action: #selector(myTargetFunction), for: .touchDown)

This is the function:

func myTargetFunction() {
    print("It works!")
}
Ibrahim
  • 6,006
  • 3
  • 39
  • 50
10

I referred to the UIControlEvents documentation from Apple and came up with the following:

First add UITextFieldDelegate to your class then,

textBox.delegate = self
textBox.addTarget(self, action: #selector(TextBoxOn(_:)),for: .editingDidBegin)
textBox.addTarget(self, action: #selector(TextBoxOff(_:)),for: .editingDidEnd)

with the following functions:

func TextBoxOff(_ textField: UITextField) {
     code
         }                
}

func TextBox(_ textField: UITextField) {
    code
         }
}
Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
Craig P
  • 477
  • 6
  • 12
8

For Swift 3.1:

1) Create a gesture recognizer:

let textViewRecognizer = UITapGestureRecognizer()

2) Add a handler to the recognizer:

textViewRecognizer.addTarget(self, action: #selector(tappedTextView(_:))) 

3) Add the recognizer to your text view:

textView.addGestureRecognizer(textViewRecognizer)

4) Add the handler to your class:

func tappedTextView(_ sender: UITapGestureRecognizer) {
        print("detected tap!")
}
drbobdugan
  • 443
  • 5
  • 12
6

To make this a little clearer these things need to be in place. I used this to make it so if a user entered something in an app of my own's credit textField anything in the debit textField is deleted.

  1. UITextFieldDelegate needs to be declared in the View controller i.e class SecondViewController:
  2. The detector functions func myDebitDetector func myCreditDetector need to be in the ViewController class.
  3. put debit.addTarget and credit.addtarget inside view will appear.

  4. @IBOutlet weak var debit: UITextField! and @IBOutlet weak var credit: UITextField! are textfields on the storyboard and connected to the viewController.

    class SecondViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
    
    @IBOutlet weak var credit: UITextField!
    @IBOutlet weak var debit: UITextField!
    
        func myDebitDetector(textfield: UITextField ){
            print("using debit")
            credit.text = ""
    
        }
    
        func myCreditDetector(textfield: UITextField) {
            print("using cedit")
            debit.text = ""
        }
    
        override func viewWillAppear(animated: Bool) {
    
    
    
            debit.addTarget(self, action: "myDebitDetector:", forControlEvents: UIControlEvents.TouchDown)
            credit.addTarget(self, action: "myCreditDetector:", forControlEvents: UIControlEvents.TouchDown)
        ....
    
        }
    }
    
Wings
  • 2,398
  • 23
  • 46
Mountain Man
  • 252
  • 2
  • 10
3

Set the UITextField delegate to your view controller

Obj-C

textField.delegate = self;

Swift

textField.delegate = self

Implement the delegate method

Obj-c

-(void)textField:(UITextField*)textField didBeginEditing {
   // User touched textField
}

Swift

func textFieldDidBeginEditing(textField: UITextField!) {    //delegate method

}
Lytic
  • 786
  • 5
  • 12
2

Swift 3.0 Version:

textFieldClientName.addTarget(self, action: Selector(("myTargetFunction:")), for: UIControlEvents.touchDown)
Nazmul Hasan
  • 10,130
  • 7
  • 50
  • 73
Matheus Faleiro
  • 101
  • 1
  • 8
1

Swift 4.2.

Try .editingDidEnd instead of .touchDown and delegate.

myTextField.addTarget(self, action: #selector(myTargetFunction), for: .editingDidEnd)

@objc func myTargetFunction(textField: UITextField) {
    print("textfield pressed")
}
Andy
  • 185
  • 1
  • 13
0

On xamarin.iOS i easy to use:

YourTextField.WeakDelegate = this;

[...]

[Export("textFieldDidBeginEditing:")]
public void TextViewChanged(UITextField textField)
{
    if (YourTextField.Equals(textField))
        IsYourTextFileFocused = true;
}
Maury
  • 604
  • 2
  • 8
  • 25
0
** Swift 4.0 + **
Use custom action like this


YourTextField.addTarget(self, action: #selector(myTargetFunction(_:)), for: .allEditingEvents)

@IBAction private func myTargetFunction(_ sender: Any) {
        if let textField = sender as? UITextField {
            // get textField here
        }
    }