I have a ViewController set as a delegate for a UITextField. No matter what I try, I can not get the keyboard to hide when calling textFieldShouldReturn.
My viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(newModelField)
newModelField.delegate = self
self.presetTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "presetCell")
//self.view.becomeFirstResponder()
}
and my textFieldShouldReturn method:
func textFieldShouldReturn(textField: UITextField) -> Bool {
//UIApplication.sharedApplication().sendAction("resignFirstResponder", to:nil, from:nil, forEvent:nil)
if(textField.text! != ""){
items.append(textField.text!)
presetTableView.reloadData()
textField.text! = ""
//self.view.resignFirstResponder()
//self.addView.resignFirstResponder()
//textField.endEditing(true)
//self.view.endEditing(true)
UIApplication.sharedApplication().delegate?.window?!.endEditing(true)
return false
}
return true
}
You can see from my commented out attempts that I have tried a whole host of different fixes. I know that textFieldShouldReturn is being called after debugging with print statements. I can not figure out why the keyboard won't hide.
I tried swapping the return true and false statements. I tried setting the delegate from the storyboard. I tried deleting the textField from storyboard, cleaning, and adding it back in. I tried all top level calls to resignFirstResponder and endEditing as well as calls to these functions for the textfield and the view.
To dismiss the keyboard, send the resignFirstResponder message to the text >field that is currently the first responder. Doing so causes the text >field object to end the current editing session (with the delegate >object’s consent) and hide the keyboard.
yourTextField.resignFirstResponder()
I tried using resignFirstResponder() on textFiled and also used endEditing(true) on my view but I did this small mistake of implementing this other delegate and was returning false
func textFieldShouldEndEditing(textField: UITextField) -> Bool { //delegate method
return true
}
Related
I'm learning Swift by making a times tables app, which simply creates random times tables and asks the user to type the answer in a UITextField.
I'd like the user to be able to tap the return key and have the text field clear their previous answer and have the keyboard remain in view. I've already set up the other behaviour I want, it's just I can't seem to find any similar questions to figure out how to clear, and do all this when there return key is tapped.
Here's the code I have so far, which works when dismissing the keyboard, and doesn't clear the field.
Many thanks!
#IBAction func answerTyped(_ sender: UITextField) {
/* Clear the text field*/
questionNumber += 1
attempted += 1
markQuestion(answer: answer)
newQuestion(awardLevel: currentLevel, questionNumber: questionNumber)
}
If you want the textField to be cleared on tapping return button you can use the textFieldShouldReturn delegate.
func textFieldShouldReturn(_ textField: UITextField) -> Bool { //delegate method
textField.text = "" // Clears text
//Do other things that you want to do when user taps return button
return true
}
Note that this wont dismiss the textField like how you asked and usually users are used to dismissing their textField using return. So if you ask me this is not good UX. And you need to have a mechanism for the user to dismiss the keyboard if needed like tap outside to dismiss or something. So i hope you have that sorted out.
Your viewController should have implemented the UITextFieldDelegate for this method work.
class YourViewController: UITextFieldDelegate {
var textField: UITextField! //Using IBOutlet or whatever
func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
}
}
you will need to make something, likely your view controller containing this text field into a uitextfieldelegate, then add the necessary delegate functions.
I think the function you want is TextField:DidEndEditing:Reason https://developer.apple.com/documentation/uikit/uitextfielddelegate/2352220-textfielddidendediting
Or you can just use
func textFieldShouldReturn(_ textField: UITextField) -> Bool { //delegate method
textField.resignFirstResponder()
return true
}
which is called every time user hits the return key. You would need to add your logic to clear the contents before the returns.
I'm trying to modify the text rendered in the UITextField based on certain events such as Touch Down or Touch Down Repeat. I want the UITextField to be responsive only to events but prevent users from modifying the actual value in the UITextField.
I have tried unchecking the Enabled state of the UITextField but that causes it to not respond to touch events either.
How do I prevent users from changing the contents of the UITextField without affecting the response to touch events, specifically using Swift 3?
So, I was finally able to get this working in the expected manner. What I did was -
1 - Extend the UITextFieldDelegate in the ViewController class
class ViewController: UIViewController, UITextFieldDelegate {
2 - Inside the function viewDidLoad(), assign the textfield delegate to the controller
override func viewDidLoad() {
super.viewDidLoad()
textfield.delegate = self
}
(you will have assign each UITextField's delegate that you want to be prevented from editing)
3 - Lastly, implement your custom behavior in the textFieldShouldBeginEditing function
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}
For reference, check out this API Reference on Apple Developer
Override textFieldShouldBeginEditing , and return false.
func textFieldShouldBeginEditing(state: UITextField) -> Bool {
return false
}
you can also disable for specific text field.
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if(textField == self.myTextField){
return false
}
return true;
}
I happening the following problem:
I have two TextField, one has the default behavior, and on the other, captures the textFieldDidBeginEditing method delegate, to present a UIViewController with PresentationStyle (Custom) and TransitionStyle (CrossDissolve). So far everything works fine. But if I edit the first textField (and leave the keyboard open) and then go to the second, the keyboard is open and I have no way to close it (as if the first textField had lost focus, not even the textFieldShouldReturn is called when I press the button intro).
I tried with:
TextFieldDidEndEditing (for calling resignFirstResponder)
In viewWillDissaper method (I also called resignFirstResponder)
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(textField: UITextField) {
print("Resign Last TextField")
textField.resignFirstResponder()
}
func textFieldDidBeginEditing(textField: UITextField) {
print("Did Begin editing")
if textField == self.departing || textField == self.returning{
textField.resignFirstResponder()
self.lastTextFieldSelected = textField
let datePickerViewController = Util.getViewController("DatePickerViewController") as! DatePickerViewController
datePickerViewController.dateStyle = NSDateFormatterStyle.ShortStyle
datePickerViewController.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
datePickerViewController.modalPresentationStyle = UIModalPresentationStyle.Custom
datePickerViewController.datePickerDelegate = self
self.presentViewController(datePickerViewController, animated: true, completion: nil)
}
}
Edit:
I try with self.view.endEditing(true) nothing.
I made a little example (something I check, is that textFieldShouldBeginEditing allows me to close the keyboard.):
https://github.com/Abreu0101/TextFieldBug
It looks like your textFieldDidEndEditing and the other methods are not even called. Make sure you set the UITextField's delegate:
textField.delegate = self
Also import the UITextFielDelegate in your class.
Hope that helps :)
i'm trying to change the default action when user press on a text field. I tried to connect my action at Editing Did Begin event using storyboard as you can see below. The problem is that the keyboard always appear but I want that the keyboard doesn't never appear.
I cannot delete text field delegate methods cause i have others text field in the same view.
How can i do?
Set your view controller as your textField delegate and implement UITextField textFieldShouldBeginEditing delegate method.
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == yourTextField {
// implement custom behaviour
return false
}
return true
}
Update
Try this for single textfield keyboard never show
func textFieldDidBeginEditing(textField: UITextField) {
if textField == yourTextField
{
textField.inputView = UIView()
}
}
Simple:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if(textField == YourtextField){
return false
}
return true
}
OR:
in your viewDidLoad() set yourTextField.inputView = UIView()
Works in both ways. Use suitable one.
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()
}