How to move one text field to another using keyboard return key in swift3 ios - ios

By this img with done btn to move at next textfield (https://i.stack.imgur.com/cDHlh.jpg)

I doubt if you can do that with the 'Done' button, but you may achieve that with the return key by
Make your class a UITextField Delegate
class VC: UIVIewController, UITextFieldDelegate
In your ViewDidLoad method do this -
textField1.becomeFirstResponder()
So that when user comes in this screen the 1st textfield will directly become active(not the right word but using this word for lack of better alternative)
And when you need it to move to the next textfield when he presses return,
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField1.resignFirstResponder()
if (textField == textField1){
textField2.becomeFirstResponder()
}
else if (textField == textField2){
textField3.becomeFirstResponder()
}
return true
}
You may use a switch case too in the above delegate method. And as mentioned in the comment in the question, do go through the link and know how to properly ask questions, giving as much detail as possible.

Related

Swift 5 Custom Textfield Delegate not working

Ever since I updated my Xcode and project to Swift 5,
I have this incredibly weird issue with specific textfields.
These text fields have a custom class to allow a response to a swipe action. They also have a special response to a standard touch. When the text field is touched, the textFieldShouldBeginEditing function suppresses the keyboard raise and instead launches a custom pull out value selection menu.
All was working perfectly until the update, where, whenever I start my Xcode up (after a day or two) and load my app, the textFieldShouldBeginEditing for these fields is never called!
What cures them (riduculously) is going to each View Controller that has one of these custom textfields - and making a single stroke edit to the page.
Then, when I reload, the textfields on that particular view are good again.
But the problem happens all over again, a few days later after I reload the app.
And I can't seem to replicate the problem by merely shutting down Xcode or even my computer. It seems it has to be shut down for some random amount of time or something.
...I don't know what causes this.
One other point - is that the IBOutlets for the custom selection pane is on a parent Class that is parent to all of these view controllers.
It would take a ton of writing to distribute all of the parent codes to all of the children view controllers.
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
var boolVal = true
switch textField.tag {
case 11: boolVal = false; launchSelection(textField)
case 12: boolVal = false; launchSelection(textField)
default: boolVal = true; shutThatStupidSideBar()
}
textFieldTag = textField.tag
return boolVal
}
func launchSelection(_ tf:UITextField) {
selectionPane.textfield = tf
switch tf.tag {
case 11: selectionPane.tableData = lm.retreiveList("provider") //11 = Owner
case 12: selectionPane.tableData = lm.retreiveList("\(currentSettings.defUnitsStrand)GaugeStrand") //12 = Strand Gauge
default: break
}
toggleSideBar()
}
Check UITextField delegate to UIViewController in storyboard
Add UITextFieldDelegate to viewController code like This:
class ViewController: UIViewController, UITextFieldDelegate
Use this sample code:
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
print("Test")
return true
}

Enabling a specific UITextField if another UITextField has a certain value

I have two UITextFields, cDiseasePicker and optionalLMS.
My cDiseasePicker uses a UIPickerView as input, with the options "No", "Yes, 1VD", "Yes, 2VD", and "Yes, 3VD".
If the user chooses "No", then optionalLMS should be greyed out/user interaction disabled. Otherwise, they should be allowed to edit it.
I've tried adding
func textFieldDidEndEditing(_ textField: UITextField) {
if cDiseasePicker.text == "Yes, 1VD" || cDiseasePicker.text == "Yes, 2VD" || cDiseasePicker.text == "Yes, 3VD" {
optionalLMSText.isUserInteractionEnabled = true
print("true cdisease")
} else if cDiseasePicker.text == "No" {
optionalLMSText.isUserInteractionEnabled = false
print("false cdisease")
}
}
But this seems to have no effect, and nothing is printed to the console.
This is my class declaration, if that makes a difference:
class NewRecord: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate
Apologies if this is a basic question, I'm still fairly new to Swift.
As you're using a UIPickerView as input, you should look at your picker view didSelectRow (which I guess you are using to populate your cDiseasePicker textfield) to configure the other textfield to your liking.
If I understand correctly the key information you need is that textFieldDidEndEditing method is called when the text field is no longer the first responder, not when the text changes.

UITapGestureRecognizer on a text field not as expected

In my class I have 11 UITapGestureRecognizers in an array textViewRecognizer attached to 11 out of 100 UITextFields in an array boxArray. When a Textfield is tapped containing a UIGestureRecognizer it runs tappedTextView where I try to get the index of the first responder.
However, due to some weird ordering in how things are executed, the action function only gives me the first responder of the previous first responder to the one that was just tapped.
Also, I have to double tap to even select the text field I was going for! I need to use the tap function and not the text delegates so this has been a real headache.
I have...
#objc func tappedTextField(_ sender: UITapGestureRecognizer) {
for i in 0...99 {
if (boxArray[i]?.isFirstResponder)! {
if let index = boxArray.index(of: boxArray[i]) {
print(index)
break
}
}
}
}
in my viewDidLoad I have
for i in 0...10 {
textFieldTapRecognizer[i].addTarget(self, action: #selector(self.tappedTextField(_:)))
}
In my class I have
I want to set 11 out of 100 textFields to have this a tap recognizer depending on some conditions (I'm just going to use a regular for loop here)
for i in 0...10 {
boxArray[i]?.addGestureRecognizer(textFieldTapRecognizer[i])
}
Is there anyway I can get it to give me the actual first responder, after the tap was made?
Is there anyway to go around the double tap to select the text field that has a UITapGesture?
Any help is greatly appreciated.
Edited: properly named functions
It sounds like you want to remove the automatic editing behavior on a UITextView. You can grab more control over that with the textViewShouldBeginEditing(_ textView: UITextView) -> Bool UITextViewDelegate method, documented here.
If you return false for that method, this should avoid needing a double tap to get to your gesture recognizer. Depending on your use case, you can then "allow" the tap to go to the text view by returning true for the textView you want to be actually edited.
While I'm not 100% clear on the first responder part of your question, since the textView won't be grabbing first responder if it's not starting it's editing mode, this should address that concern I believe. Good luck!
I would add a Tag to my UITextView and set the UITextViewDelegate to my ViewController.
Then I would add the following Delegate method:
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
print("Textview tag: ", textView.tag)
return false
}

iOS hiding keyboard on "Return" press, resignFirstResponder vs endEditing

I was searching for hiding the iOS keyboard when you press "return", and about half the answers are to use self.view.endEditing(true) and the other half textField.resignFirstResponder(). Is one a better way than the other?
For reference or anyone coming here from Google or something, you need to add UITextFieldDelegate to your class inheritance, add self.<your_TF_var_name>.delegate = self in viewDidLoad(), then make a function
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
//OR
textField.resignFirstResponder()
return true
In this case, it doesn't really matter which you use though technically, using textField.resignFirstResponder() is more efficient because you already know that is the text field you need to resign.
The call to self.view.endEditing(true) is going to have to figure out what the current first responder is and then call resignFirstResponder on it.
My general rule of thumb is to use resignFirstResponder if you have a reference to a specific view you wish to resign. And use endEditing if you don't and you just want the current first responder to be resigned.
On a side note, you should return false from textFieldShouldReturn in either case. There is an edge case where returning true can lead to a newline being added to a UITextView after resigning the UITextField. So as a rule I always return false.

Why call method to resignFirstResponder from textFieldShouldBeginEditing?

I am trying to understand delegate methods in general, and specifically how to dismiss a UIDatePicker that popovers from a text field.
According to the documentation, textFeildShouldBeginEditing returns true 'if an editing session should be initiated; otherwise, false to disallow editing.'
Why would I then tell the app to resignFirstResponder, which is meant to hide the keyboard / date picker (as in several examples on stackoverflow and noobie tutorials)?
What I don't understand is: if it should begin editing, why then hide the input devise? Obviously, I am misunderstanding one or both concepts.
func resign() {
dobTextField.resignFirstResponder()
nameTextField.resignFirstResponder()
println("resign gets printed, but the date picker is still visible!?!")
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if (textField === dobTextField) {
resign() // but should begin editing, oder?!?
}
In the examples you cite, the textField is being used to display a date. When the user selects this field, the app designers want the UIDatePicker to be displayed instead of the keyboard. Hence they call resignFirstResponder to hide the keyboard. At the same time, they display the date picker.
ResignFirstResponder will not hide the date picker, so the "input device" (for this field) will still be available.
Also, note that in one case the developer has used textFieldShouldBeginEditing, and returns false because they are providing the date picker. In the other case the developer uses textFieldDidBeginEditing (which has no return value).
you should resign only the textfield not affected:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == dobTextField {
nameTextField.resignFirstResponder()
} else if textField == nameTextField {
dobTextField.resignFirstResponder()
}
return true
}
this way you are resiging first responder only on the textfields that should not currently be edited. this helps if for some reason you accidentally have 2 textfields (or more) assigned first responder causing conflicts with multiple keyboards/datepickers and such.

Resources