UITextField returns value held before edit - ios

I have textField. For that textField, I added the following target and function.
textField.addTarget(target: self, action: #selector(self.textDidChange), for: UIControlEvents.editingChanged)
func textDidChanged() {
label.text = textField.text
}
Strange thing I encounter is whenever the textDidChanged is called textField returns the previous state of value.
Eg: What I entered in TextFiled --> What I got in Label
"a" ----> ""
"aa" ----> "a"
"a" ----> "aa"
textField.text return value before my edit.
Is it something wrong in my doing. Guide me. Thanks.

override func viewDidLoad() {
super.viewDidLoad()
self.textfield.addTarget(self, action: #selector(textDidChanged), for: UIControl.Event.editingChanged)
}
#objc func textDidChanged() {
label.text = textfield.text
}
This works in Xcode10.

Related

Swift: textField listener not responding to text change

FYI: I am a JS developer, and recently started learning Swift. So I am not sure I am using the right terminology here.
In my app, I have a simple textField:
It is linked to this outlet:
#IBOutlet weak var activationCodeTextField1: UITextField!
The "listener" is implemented as follows:
self.activationCodeTextField1.addTarget(self, action: #selector(self.textField1DidChange(_:)), for: UIControl.Event.editingChanged)
self.activationCodeTextField1.delegate = self
textField1DidChange function:
#IBAction func textField1DidChange(_ sender: AnyObject) {
print("TextField1DidChange")
}
But, when I type something in the TextField, nothing gets printed.
So maybe textField1DidChange does not get triggered for some reason?
But, I really do not why.
Update: Here is the sample code for you to test in playgrounds.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textField = UITextField()
textField.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
textField.placeholder = "enter text here"
textField.center = view.center
view.addSubview(textField)
textField.addTarget(self, action: #selector(textChanged), for: .editingChanged)
}
#objc func textChanged(_ sender: UITextField) {
print(sender.text)
}
}
PlaygroundPage.current.setLiveView(ViewController())
The event valueChanged should be used to detect to see if the text has changed. editingChanged detects if the state of UITextField has changed between editing or idle states.
Replace:
self.activationCodeTextField1.addTarget(self, action: #selector(self.textField1DidChange(_:)), for: UIControl.Event.editingChanged)
With:
activationCodeTextField1.addTarget(self, action: #selector(self.textField1DidChange), for: .valueChanged)
Add-on: You don't need to put self unless you're inside a closure. And don't need the entire UIControl.Event.valueChanged, you can just put .valueChanged and it'll work fine.
Remove these delegates and target method just use action for editing changed.

How to call function when editing text inside of uitextfield

so I have a login screen in my app. When the user clicks login, an api is called to check if the login credentials are correct (or not) and an error message is displayed when the login credentials are incorrect. Now the problem I'm having is after the login button is called and an error message is displayed, I want the error message to disappear when the user begins to change the text in the username/password field (UITextField). At first I tried using an event listener to try to set the alpha of the error message to 0.0 when the listener called a function. The code I used for that is down below.
textField.addTarget(self, action: #selector(textFieldDidChange(textfield:)), for: .editingChanged)
Then I had an objc function for that action:
#objc func textFieldDidChange(textfield: UITextField) {
errorLabel.alpha = 0.0
}
The problem I'm having with this is the error message disappears when the user only clicks on the textfield. I only want the error message to disappear if the user actually changes the text in the textfield. How should I go about this? Please let me know if you need anything else.
I wrote a quick version of the code
The solution is to create 2 variables which will do the work of storing the values of your credentials when they are wrong
import UIKit
class ViewController: UIViewController {
var usernameText:String? = nil
var passwordText:String? = nil
// we will use usernameText and PasswordText to keep track of the value of the textFields
let usernameField:UITextField = {
let textfield = UITextField()
textfield.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
return textfield
}()
let passwordField:UITextField = {
let textfield = UITextField()
textfield.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
return textfield
}()
override func viewDidLoad() {
super.viewDidLoad()
}
#objc func loginButtonTouched(){
if we touch your login button and the credentials are wrong {
// you will show the errorLabel
ErrorLabel.alpha = 1
// and give value to usernameText and passwordText
usernameText = usernameField.text
passwordText = passwordField.text
}else{
present(nextVC) // for example
}
}
// the username and the password textField have the same action if the text change
#objc func textFieldDidChange(_ textfield: UITextField) {
// now we will use the values we gave to usernameText and passwordText to check if one of them has changed their value
if usernameText != usernameField.text || passwordText != passwordField.text {
// if one of them changed their value we make disappear the errorLabel
ErrorLabel.alpha = 0.0
}
}
}

Replace empty UITextfield with value

I am building a digit only textfield.
I would like that when the text in textfield is "" replace it with "0".
I only manage to get the current text in read only.
Thanks in advance
Add the editingChanged delegate method to textField as follows:
In the viewDidLoad() method add the following code:
textField.addTarget(self, action: #selector(textFieldChanged(_:)), for: .editingChanged);
And then, implement the method as follows:
#objc func textFieldChanged(_ textField: UITextField) {
if let text = textField.text, text.isEmpty {
textField.text = "0"
}
}
The above method will be called every time the textField content changes.
You can also set the initial text of the textField to "0". Simply use textField.text = "0" in the viewDidLoad() method.
If you want the text field to update when you have finished editing you can set up the action like this
and then
#IBAction func editingDidEnd(_ txtTest: UITextField) {
if txtTest.text == ""
{
txtTest.text = "0"
}
textField.addTarget(self, action: #selector(handleTextField(_:)), for: .editingChanged)
#objc private func handleTextField(_ textField: UITextField) {
if textField.text == "" {
textFiled.text = "0"
}
}

UITextField function not available in UITextView

I'm having a problem with applying a textField function in terms of a textView.
Previously, I was using a textField and the below code was running smoothly without any problem. Now, I decided to use a textView instead of a textField, so want to change every textField to a textView but don't know how to implement the textField.addtarget() function to a textView. What I want is, initially, when the textView is empty the button color isn't enabled but when there is text in it, the button color should be blue.
I can't find a proper function that contains a #selector to call my main function in the textView functions. I'd appreciate any help. Thank you very much in advance!
override func viewDidLoad() {
super.viewDidLoad()
buttonColor.isEnabled = false
handleTextField()
}
func handleTextField() {
textField.addTarget(self, action: #selector(self.textFieldDidChange), for: UIControlEvents.editingChanged)
} // used to call the main function
#objc func textFieldDidChange() {
if (textView.text != ""){
buttonColor.setTitleColor(UIColor.blue, for: UIControlState.normal)
buttonColor.isEnabled = true
return
}
buttonColor.setTitleColor(UIColor.lightGray, for: UIControlState.normal)
buttonColor.isEnabled = false
}
You have a delegate for it in UITextViewDelegate called textViewDidChange(_:).
class ViewController: UIViewController, UITextViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
yourTextView.delegate = self
print(locationName) // not important
buttonColor.isEnabled = false // not important
}
//Your other code
func textViewDidChange(textView: UITextView) {
if (textView.text != ""){
buttonColor.setTitleColor(UIColor.blue, for: UIControlState.normal)
buttonColor.isEnabled = true
return
}
buttonColor.setTitleColor(UIColor.lightGray, for: UIControlState.normal)
buttonColor.isEnabled = false
}
}

textfield click vs drag

I have a text field which can be clicked to edit, and dragged along the y-axis using a UIPanGesture.
When the user clicks the text field, I want to set the textAlignement to.left & when the user drags the text field around, I want to keep the text center aligned.
I initialise in the viewDidLoad method:
let dragText = UIPanGestureRecognizer(target: self, action: #selector(userDragged))
textOverlay.addGestureRecognizer(dragText)
textOverlay.addTarget(self, action: #selector(textClicked), for: UIControlEvents.touchDown)
Callback methods:
func textClicked() {
//let actLocation = textOverlay.frame.origin.y
textOverlay.frame.origin.y = self.finalKBH
self.textOverlay.textAlignment = .left
print("Text clicked")
}
func userDragged(gesture: UIPanGestureRecognizer) {
let loc = gesture.location(in: self.view)
self.textOverlay.frame.origin.y = loc.y
self.textOverlay.textAlignment = .center
print("Text dragged")
}
The problem I'm having, is differentiating between an actual 'click-to-edit' and drag gesture.
While dragging the text field, the textClicked function is also called and the text is aligned to the left.
Is there a way I can differentiate between these two actions?
I've attempted to change the textClicked targer to UIControlEvents.touchUpInside but then my function isn't being registered in the console.
Many thanks in advance
For detecting when the textfield enters editing mode, implement the textFieldDidBeginEditing(_:) method of UITextFieldDelegate
override func viewDidLoad()
{
super.viewDidLoad()
// ...
textField.delegate = self
}
func textFieldDidBeginEditing(_ textField: UITextField)
{
print("Text clicked")
}
Maybe, long press if you have to use an overlay for some reason?
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
textOverlay.addGestureRecognizer(longPressRecognizer)

Resources