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
}
}
Related
[if all textfield is fill it will easily come back but if all textfield is empty and i click on last textfield then i want to come back to the previous textfield and so on how i achieved this please help me ]
import UIKit
class OTPVC: CommonViewController,UITextFieldDelegate {
#IBOutlet weak var aboutOtp: UIView!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var bottomConstraint: NSLayoutConstraint!
#IBOutlet weak var firstOtptxt: UITextField!
#IBOutlet weak var secondOtptxt: UITextField!
#IBOutlet weak var thirdOtptxt: UITextField!
#IBOutlet weak var fourthOtptxt: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
setUpView()
firstOtptxt.delegate = self
secondOtptxt.delegate = self
thirdOtptxt.delegate = self
fourthOtptxt.delegate = self
}
private func setUpView() {
aboutOtp.makeCornerRadius(10)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if ((textField.text?.count)!) < 1 && (string.count > 0) {
if textField == firstOtptxt{
secondOtptxt.becomeFirstResponder()
}
if textField == secondOtptxt {
thirdOtptxt.becomeFirstResponder()
}
if textField == thirdOtptxt {
fourthOtptxt.becomeFirstResponder()
}
if textField == fourthOtptxt {
fourthOtptxt.becomeFirstResponder()
}
textField.text = string
return false
} else if (((textField.text?.count)!) >= 1) && (string.count == 0) {
if textField == secondOtptxt {
firstOtptxt.becomeFirstResponder()
}
if textField == thirdOtptxt {
secondOtptxt.becomeFirstResponder()
}
if textField == fourthOtptxt {
thirdOtptxt.becomeFirstResponder()
}
if textField == firstOtptxt {
firstOtptxt.becomeFirstResponder()
}
textField.text = string
return false
}
else if ((textField.text?.count)!) >= 1 {
textField.text = string
return false
}
return true
}
}
[if all textfield is fill it will easily come back but if all textfield is empty and i click on last textfield then i want to come back to the previous textfield and so on how i achieved this please help me ]
[if all textfield is fill it will easily come back but if all textfield is empty and i click on last textfield then i want to come back to the previous textfield and so on how i achieved this please help me ]
protocol MyTextFieldDelegate: UITextFieldDelegate {
func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool)
}
class MyTextField: UITextField {
override func deleteBackward() {
// see if text was empty
let wasEmpty = text == nil || text! == ""
// then perform normal behavior
super.deleteBackward()
// now, notify delegate (if existent)
(delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
}
}
[just put a delegate method and its work fine in my project yippy]
there is a trick, you can have a 'space' in your textfields, so that problem will be solved .
How to start a new line in UITextView with a little space, called paragraph I believe?
What you need to do is make the controller confront to UITextFieldDelegate
for example:
class ViewController: UIViewController,UITextFieldDelegate
{
//link the textfield
#IBOutlet weak var textField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
// link the delegate to the textfield
textField.delegate = self
}
//this function detects the return button when it's pressed
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
//since we always want to start a new line with space we override the default function
textField.text += "\n "
return false
}
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'm trying to convert a UITextField object to a String so that I can pass it to a function in my model file. But it is printing a blank even after I type in some characters in the name input text field and then click outside of it. Why is nothing stored there?
In view controller file:
#IBOutlet weak var nameInputText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
nameInputText.delegate = self
let text: String = nameInputText.text!
print(text) //this prints a blank
model.validateName(nametext: text)
}
It should be like below
#IBOutlet weak var usernameInputText : UITextField!
override func viewDidLoad() {
super.viewDidLoad()
usernameInputText.delegate = self
}
func ClickOnButton()
{
let text: String = usernameInputText.text!
print(text) //this prints My text
model.validateName(nametext: text)
}
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String)
-> Bool
{
let text: String = usernameInputText.text!
print(text) //this prints My text
model.validateName(nametext: text)
}
viewDidLoad gets called before your ViewController would be visible to the user, so any text field can only contain text if you have set that text before (in InterfaceBuilder or code). If you want to access user input from that text field, you should either do that in textFieldDidEndEditing or in any other function which you know can only be called after the user interaction happened.
#IBOutlet weak var nameInputText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
nameInputText.delegate = self
}
extension ViewController: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
model.validateName(nametext: textField.text)
}
}
I have a button that is disabled in my view controller. I have IBActions for when two text fields are edited. I am trying to enable the button when two text fields both contain integers. I have tried to do this, but whenever I run the ios simulator, the button stays disabled even when I put integers into each text field. Why is it staying disabled? I am new to swift, so please help me out. Here is the code for my entire project:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var calculatorButton: UIButton!
#IBOutlet weak var inspirationLabel: UILabel!
#IBOutlet weak var beginningLabel: UILabel!
#IBOutlet weak var calculatorContainer: UIView!
#IBOutlet weak var answer1Label: UILabel!
#IBOutlet weak var doneButton: UIButton!
#IBOutlet weak var yourWeightTextField: UITextField!
#IBOutlet weak var calorieNumberTextField: UITextField!
#IBOutlet weak var menuExampleButton: UIButton!
#IBOutlet weak var aboutButton: UIButton!
#IBOutlet weak var calculateButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib
yourWeightTextField.delegate = self
calorieNumberTextField.delegate = self
calculateButton.enabled = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func calculatorButtonTapped(sender: AnyObject) {
calculatorContainer.hidden = false
inspirationLabel.hidden = true
beginningLabel.hidden = true
menuExampleButton.hidden = true
aboutButton.hidden = true
}
#IBAction func yourWeightEditingDidEnd(sender: AnyObject) {
yourWeightTextField.resignFirstResponder()
}
#IBAction func calorieNumberEditingDidEnd(sender: AnyObject) {
calorieNumberTextField.resignFirstResponder()
}
var yourWeightFilled = false
var calorieNumberFilled = false
func yourWeightTextFieldValueValidInt(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (yourWeightTextField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if let intVal = text.toInt() {
self.yourWeightFilled = true
} else {
self.yourWeightFilled = false
}
return true
}
func calorieNumberTextFieldValueValidInt(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (calorieNumberTextField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if let intVal = text.toInt() {
self.calorieNumberFilled = true
} else {
self.calorieNumberFilled = false
}
return true
}
#IBAction func yourWeightTextFieldEdited(sender: AnyObject) {
if self.yourWeightFilled && self.calorieNumberFilled {
self.calculateButton.enabled = true
}
}
#IBAction func calorieNumberTextFieldEdited(sender: AnyObject) {
if self.yourWeightFilled && self.calorieNumberFilled {
self.calculateButton.enabled = true
}
}
}
Your delegate methods are a bit mixed up -- they have to be named exactly what the caller expects, or they won't be found, so yourWeightTextFieldValueValidInt() and calorieNumberTextFieldValueValidInt() aren't being called at all. Instead you'll need to handle the edits to both text fields in a single method:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if textField == yourWeightTextField {
yourWeightFilled = text.toInt() != nil
} else if textField == calorieNumberTextField {
calorieNumberFilled = text.toInt() != nil
}
return true
}