iOS - Add Tap Gesture to UITextField - ios

I have problem with add a Tap Gesture to my UITextField. Below code:
#IBAction func hanldeTap(recognizer: UITapGestureRecognizer) {
println("works")
}
This action is associated with Tap Gesture Recognizer. In my TextField I have defined gestureRecognizer in OutletCollections. In my guess it should works. In described configuration gesture works e.x. for button or custom view.
Can you tell my what could go wrong and how can I fix this?

UITextField has delegate methods, you might want to consider implementing those. Or just add action event to your textfield.
For example in viewDidLoad
textField.addTarget(self, action:Selector("textDidBeginEditing"), forControlEvents: UIControlEvents.EditingDidBegin)
Then implement this:
func textDidBeginEditing(sender:UITextField) -> Void
{
// handle begin editing event
}

If you set the textfields delegate, you can use;
optional func textFieldDidBeginEditing(_ textField: UITextField)
or
optional func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool
etc

textField.addTarget(self, action:#selector(textDidBeginEditing), for: UIControl.Event.editingDidBegin)

Swift 4.2
Adding to the accepted answer
Don't forget to add '#' before selector (with small s) i.e. #selector
textField.addTarget(self, action: #selector(textDidBeginEditing), for: UIControl.Event.editingDidBegin)
And do add #objc before the function. like
#objc func textDidBeginEditing(sender:UITextField) -> Void

Related

How to update the text of a UILabel when the user fill in some Text Fields

I need to update a Label with the text the user has typed in some Text Field on the same Screen.
If possible I'd prefer to update it as the user types.
You can listen to the textfield changes by adding a target for event UIControl.Event.editingChanged and update your label in the selector function. You can add target to the text field as follows.
textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
And in the objc function, you can update the label content.
#objc func textFieldDidChange(_ textField: UITextField) {
label.text = textField.text
}
yes it is possible
if you are using interface builder
make a new #IBAction from your textField like in the image
and choose Editing Did Change
#IBAction func tfUpdate(_ sender: UITextField) {
label.text = sender.text
}

Open view when tapping the text field without opening the keyboard [duplicate]

This question already has answers here:
Disable UITextField keyboard?
(10 answers)
Closed 4 years ago.
I am developing an app in which I want to open a view when the user clicks on a text field but I don't want to open the keyboard. How can I achieve this?
You can easily achieve it by setting an empty custom input view to the textField:
textField.inputView = UIView(frame: CGRect.zero)
Then the textField can become first responder normally, but this view (with zero frame) will be presented instead of the keyboard.
Set your ViewController as your TextFields delegate using
self.yourTextfield.delegate = self
and now implement the UITextFieldDelegate as shown below
extension ViewController : UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
//Load your VC here
return false
}
}
Thats all :) Hope it helps
You can use below textField Delegate Method
func textFieldDidBeginEditing(_ textField: UITextField) {
yourTextField.resignFirstResponder()
//code for show view
}
Hope it will help!
You can simply add a tap gesture recognizer to the text field.
let tapGestRec = UITapGestureRecognizer(target: self, action: #selector(textFieldTapped))
textField.addGestureRecognizer(tapGestRec)

UITextField not calling editingChanged event when text is autocorrected

I have a UITextField with a return key type of Done, and I've set the delegate to resign first responder status when the return button is tapped. I've also set an editingChanged action to let me know when the user edits the text. But it seems like it isn't being called in the following context.
Say the user has entered "Pizzs" into the text field. The editingChanged action is triggered and it says the text field's value is "Pizzs". Meanwhile, "Pizza" comes up as a suggestion in the keyboard suggestion bar. If they hit the space bar, the autocorrection is accepted and the editingChanged event is called, with the new text "Pizza ". But if they hit Done then the keyboard is dismissed, the text is changed to "Pizza" in the UITextField, but editingChanged is never called.
This is a bug, right? Should I report it to Apple? Or is this expected behavior because the text is being changed programmatically rather than by the user? And can anyone think of a good workaround?
You should use .allEditingEvents for this case.
textField.addTarget(self, action: #selector(didChangeText(_:)), for: .allEditingEvents)
I had the same issue, and worked around it by implementing the UITextFieldDelegate method textFieldShouldReturn(_ textField: UITextField) -> Bool, and doing the same thing there that I was doing in my editingChanged event handler.
So, I basically did this:
textField.addTarget(self, action: #selector(textFieldEditingChanged(_:)), for: .editingChanged)
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
processText()
return false
}
#objc func textFieldEditingChanged(_ textField: UITextField) {
processText()
}
func processText() {
// Process text here
}

How to dismiss keyboard with multiple UITextField

I'm a noob here and in iOS world. I am having trouble dismiss keyboard on a specific case in my very simple todo list iOS app.
I'd like the keyboard to get dismiss when user taps anywhere outside the current text field or the keyboard itself. So far, I got the keyboard dismisses just fine (thanks to you guys here in stack overflow) when user taps on the UITableView, or most element on my app. HOWEVER, when user taps on another UITextField, the keyboard does not go away.
FYI, here's the list of existing threads I researched so far but have yet to solve this issue.
1) How to dismiss keyboard iOS programmatically
2) Resigning First Responder for multiple UITextFields
3) Dismissing the First Responder/Keyboard with multiple Textfields
4) (a few more at least but I lost track :( )
Here's what I did so far:
(in viewDidLoad())
// Add 'tap' gesture to dismiss keyboard when done adding/editing to-do item
var tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapOutside:")
tap.cancelsTouchesInView = true
self.view.addGestureRecognizer(tap)
func tapOutside(tapOutside: UIGestureRecognizer) {
// Dismiss keyboard
self.view.endEditing(true)
}
#IBAction func EditingDidBegin(sender: UITextField) {
// Highlight the text field which user is editing
self.highlightTextField(sender, highlight: true)
}
#IBAction func EditingDidEnd(sender: UITextField) {
// Undo text field highlight
self.highlightTextField(sender, highlight: false)
self.view.endEditing(true) // try this option and not working
self.setEditing(false, animated: true) // try this option and not working
sender.resignFirstResponder() // try this option and not working
UIApplication.sharedApplication().becomeFirstResponder() // try this option and not working
... // below is my code to update the todo item
}
I also tried to print out all subviews.isFirstResponder() of my view. All of it return false. I also tried override touchesBegan of my UIViewController, and inside it just calls self.view.endEditing(true) and call its super's. This also does not work.
Please help. :(
TIA!
UPDATE:
You guys are awesome! :D I got it working now thanks to you guys. There were several mistakes / messed up as I'm learning new framework. So here's what I did.
1) I did not set UITextField delegate correctly.
Mistake: I ctrl-draged textfield in xcode and link my viewController as delegate and thought that should work out. I will still need to research and understand better why.
Solution: I removed that ctrl-drag link and explicitly call myTextField.delegate = self in tableView:cellForRowAtIndexPath. And that did it. Thanks #Sidewalker
2) Mistake: I have a mixed of textFieldShouldBeginEditing, etc. and #IBAction func EditingDidBegin. So I got myself into the situation where textFieldShouldBeginEditing got the call, but EditingDidBegin did not get call.
Solution: Once I set the delegate = self explicitly and stick with implementing textField... methods and not use any #IBAction for textField, things just work.
Here's one option... We're going to add a boolean flag to determine whether or not we're in a textField when an edit attempt for another textField begins
Make your class adhere to UITextFieldDelegate
class MyClass: UIViewController, UITextFieldDelegate
Don't forget to set the delegate, we'll add the flag as well
myTextField.delegate = self
var inField = false
Implement "textFieldShouldBeginEditing" and "textFieldDidBeginEditing"
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if inField {
inField = false
return false
}
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
inField = true
}
I prefer tracking things like this rather than identifying subviews as it allows the flag to be utilized elsewhere and cuts down code complexity.
Well the keyboard isn't going away because it doesn't expect to have to. The new UITextField is just becoming the first responder while the other resigns. If you don't want a textField to become the first responder if another is already, you're going to have to cut it off before it gets the chance to. I would try to implement textFieldShouldBeginEditing and figuring out the logic there.
I'm not in love with the way this looks but this should do something along those lines.
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
for subView in self.view.subviews{
if(subView.isKindOfClass(UITextField)){
if(subView.isFirstResponder()){
subView.resignFirstResponder();
return false;
}
}
}
return true;
}
First set all the UITextField (your are creating) delegate as self and create one UITextField member variable. Now implement "textFieldDidBeginEditing" delegate method and assign the textfield to your member UITextField variable. As given below
func textFieldDidBeginEditing(textField: UITextField) {
yourMemberVariable = textField;
}
So now whenever you want to dismiss the keyboard call the dismiss method on "yourMemberVariable" object. It should work !!
What I usually do is implementing this two method:
The first one add a UITapGestureRecognizer to the whole UIViewController view
func hideKeyboard() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
The second one just get called every time the user touch anywhere on the UIViewController's view
func dismissKeyboard() {
self.view.resignFirstResponder()
}
I add the first one to the viewDidLoad method of the UIViewController. Or better yet if you want to use that on all the app just make that an extension for your UIViewController.
How about doing this in viewController, It works for me
func dismissKeyboard() {
//All the textFields in the form
let textFields = [textField1, textField2, textField3, textField4, textField5]
let firstResponder = textFields.first(where: {$0.isFirstResponder ?? false })
firstResponder?.resignFirstResponder()
}

keyboard done key action swift iOS doesn't work

I'm new in stackoverflow, I have a problem with new swift code.
I have custom the return button on keyboard with "Done", but when I tap on it, don't befall anything... How can I hide the keyboard on tap it?
I have added a code (found on this site) for hide the keyboard when you tap somewhere ,not in the keyboard, but I can't custom it with tap on "done" button... Thank you before!!
You need to implement delegate method which is called when you hit done button:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
You also need to conform to UITextFieldDelegate protocol:
// I assume you override UIViewController class. If not add UITextFieldDelegate to your class
class MyViewController: UIViewController, UITextFieldDelegate
The last thing is set up your class to be a text field delegate:
textField.delegate = self
textField.delegate = self
can be replaced by
This will create the necessary connections between your View, its component and will make the textFieldShouldReturn method work as expected.
The protocol methods have new signatures (Swift 4.1). IE:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
As the protocol methods are optional, using a wrong signature will silently fail.

Resources