How does one simply chain up a few textfields for a form?
I found an old Post for obj-C here and unsuccessfully tried to "swift it".
What I tried to do:
#IBOutlet weak var nameTextfield: UITextField!
#IBOutlet weak var emailTextfield: UITextField!
nameTextfield.addTarget(target: emailTextfield, action: becomeFirstResponder(), forControlEvents: UIControlEvents.EditingDidEndOnExit)
Do you have to target the textfield in an other way than by its IBOutlet?
add this function:
func textFieldShouldReturn(textField: UITextField!) -> Bool {
textField.resignFirstResponder()
return true
}
After return is hit on each textfield the keyboard will resign. You can add tags to your textfields and then add if/else statements for different behaviors depending on which textField.tag responded if you wish.
You do not have to target the textfield by anything other than the IBOutlet for this function.
Try out this code.
func textFieldShouldReturn(textField: UITextField) -> Bool
{
if (usernameTF.resignFirstResponder())
{
passwordTF.becomeFirstResponder()
}
textField.resignFirstResponder();
return true
}
Related
In a view with multiple UITextField elements, textFieldDidChangeSelection will trigger for any editing done in any UITextField.
Can we perform some action inside this function only when a certain UITextField is edited?
class MyViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var text1: UITextField!
#IBOutlet weak var text2: UITextField!
#IBOutlet weak var text2: UITextField!
//..........
func textFieldDidChangeSelection(_ textField: UITextField) {
print(textField.text) // this code should run only for text1 for example
}
}
You just need to compare the textField to the one you want:
func textFieldDidChangeSelection(_ textField: UITextField) {
guard textField === text1 else { return }
print(textField.text)
}
Note that you should use the identity operator === not the equality operator ==.
You can do something like this:
func textFieldDidChangeSelection(_ textField: UITextField) {
if textField === text1 {
print(textField.text) // this code should run only for text1 for example
}
}
My save button is hidden with the function saveBtnHidden() in the code below. However, the save button won't reappear when text is typed into the text field. I have tried multiple solutions similar to this. Every time that I type into the text field, the save button just won't show up.
import UIKit
class TableViewController: UITableViewController, UITextFieldDelegate {
#IBOutlet weak var saveBtn: UIButton!
#IBOutlet var nicknameField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
saveBtnHidden()
}
func saveBtnHidden() {
if (nicknameField.text?.isEmpty ?? true) {
// is empty
saveBtn.isHidden = true
} else {
saveBtn.isHidden = false
}
}
#IBAction func saveBtnPressed(_ sender: Any) {
performSegue(withIdentifier: "nextPage", sender: nil)
}
}
You are getting this error because your function saveBtnHidden() is only called once in viewDidLoad(). It does not get called again when the text in your text field changes. To detect when text changes, you will need to add a target to your text field that calls a function when it changes (.editingChanged) like this:
nicknameField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
Then in the textFieldDidChange call your saveBtnHidden() function:
func textFieldDidChange(_ textField: UITextField) {
saveBtnHidden()
}
Code adapted from: How do I check when a UITextField changes?
Use delegate to be notify of any change. Delegates is a key part of iOS development and Apple's framework.
class TableViewController: UITableViewController, UITextFieldDelegate {
#IBOutlet weak var saveBtn: UIButton!
#IBOutlet var nicknameField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
saveBtnHidden()
nicknameField.delegate = self
}
func textFieldDidChange(_ textField: UITextField) {
saveBtnHidden()
}
// More of your source code below...
I have multiple textfields
#IBOutlet var emailLogin: UITextField!
#IBOutlet var passLogin: UITextField!
#IBOutlet var emailSignUp: UITextField!
#IBOutlet var passSignUp: UITextField!
as of now these aren't really needed, because of how I am dismissing it by tapping anywhere on the screen, however I also want it to dismiss when I press the return key.
override func viewDidLoad() {
super.viewDidLoad()
self.emailLogin.delegate = self
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(LoginViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
First question: When I need to dismiss with only one I would set the delegate like so, but how do I handle this when I have multiple views that need to be dismissed on return key?
Also, there are two separate views, but both use the same class. Is this a problem for what I am trying to do?
From here
func dismissKeyboard() {
view.endEditing(true)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
This dismisses the keyboard but only for the textfield that I set as self.
Any info is appreciated!
EDIT:
Change your code to the following and it should work:
#IBOutlet var emailLogin: UITextField?
#IBOutlet var passLogin: UITextField?
#IBOutlet var emailSignUp: UITextField?
#IBOutlet var passSignUp: UITextField?
emailLogin?.delegate = self
passLogin?.delegate = self
emailSignUp?.delegate = self
passSignUp?.delegate = self
The IBOutlets from other class were not initialized when your LoginViewController loads, thus end up with unwrapping nil objects, which is not allowed in Swift. (You should be able to see that in your console output in Xcode.) Use optional variables will prevent that from happening.
Use ViewControllerDelegate to handle tap outside of any textField and textView. It will dismiss keyboard when you tap on outside of textField. Put below code in your view controller:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesBegan(touches, withEvent:event)
self.view.endEditing(true)
}
You don't need to add TapGesture now to handle this.
I am making a "To Do List" app where you can enter what to do and click submit and it shows up in a table view.
I want to add a time as well, but I cant figure out how to connect a datepicker with the "submit" button then have the time show up in the table view.
can anyone help? thank you.
#IBOutlet weak var date: UIDatePicker!
#IBOutlet weak var item: UITextField!
#IBAction func addItem(sender: AnyObject) {
self.view.endEditing(true)
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
here is the code for the add item page
i'm currently facing a problem in swift.
I implemented a method to make textfield next responder on returnkey tap, and o make it fonctional i have to make my textfields delegate (everything work on my other class).
The problem is, i also implemented a UIPickerView , which appear when "textfieldcategorie" is tapped, this pickerview need to be delegate, to put the choosen value in the textfield.
by the way, the method to make textfield nextresponder not working anymore, at the moment where i put the textfield in delegate , it become inactive.
this is the code is used :
declaration of my variable :
#IBOutlet var textfieldcategorie: UITextField!
#IBOutlet var keyword: UITextField!
#IBOutlet var codepostal: UITextField!
#IBOutlet var prix: UITextField!
#IBOutlet var pickercategorie: UIPickerView! = UIPickerView()
The method to show uipickerview on tap :
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
pickercategorie.hidden = false
return false
}
The method to make textfield nextresponder :
func textFieldShouldReturn(textField: UITextField) -> Bool {
//delegate method
if textField == keyword {
textfieldcategorie.becomeFirstResponder()
}
return true
}
}
I don't know if it's important, but i also use theses methods :
to move up the textfield when the keyboard appears :
func textFieldDidBeginEditing(textField: UITextField) {
animateViewMoving(true, moveValue: 25)
}
func textFieldDidEndEditing(textField: UITextField) {
animateViewMoving(false, moveValue: 25)
}
func animateViewMoving (up:Bool, moveValue :CGFloat){
var movementDuration:NSTimeInterval = 0.3
var movement:CGFloat = ( up ? -moveValue : moveValue)
UIView.beginAnimations( "animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration )
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
UIView.commitAnimations()
}
//Fin Monter la vue lorsque le clavier apparait
And to dismiss the keyboard on tap anywhere in the view:
func DismissKeyboard(){
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
Thank's
I feel you must change your code as follows:
func textFieldShouldReturn(textField: UITextField) -> Bool {
//delegate method
if textField === keyword {
textfieldcategorie.becomeFirstResponder()
}
return true
}
The reason being == operator checks equality of two objects but === operator check identity of two objects i.e. wether these two refer to the same object.
Also pleas change:
#IBOutlet var pickercategorie: UIPickerView!