Detecting if the user is typing? - swift

For a UITextField, what is the best way to detect if the user is typing and the textfield has a value?
I've tried the following unsuccessfully:
Value Changed: no response
Editing Did End: no response
Touch Up Inside: doesn't trigger until after the user clicks out of the textfield

Try using the shouldChangeCharactersInRange event.
func textField(textField: UITextField,
shouldChangeCharactersInRange range: NSRange,
replacementString string: String)
-> Bool {
// Put your code here
}
This is called whenever a user adds or removes a new character to your UITextField.
If you want to accept the change, return true. Otherwise return false.
Just make sure your UITextField conforms to the UITextFieldDelegate Protocol

Related

how to remove character when backspace is pressed swift

i want to remove one last character when user presses the backspace
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.isEmpty {
print("backspace pressed")
if let itemToRemove = textField.text?.dropLast(){
let text = textField.text?.replacingOccurrences(of: itemToRemove, with: "")
textField.text = text
return true
}
}
return true
}
this function clears all the elements present in the textfield
You're using this method wrong. The delegate method is not for you to implement the change to the text, it's for you to approve the change (hence returning a bool).
From the documentation (which is always a good first point of call if something isn't working how you expect):
Return Value
true if the specified text range should be replaced;
otherwise, false to keep the old text.
Discussion
The text field calls this method whenever user actions cause its text to change. Use this
method to validate text as it is typed by the user. For example, you
could use this method to prevent the user from entering anything but
numerical values.
EDIT: (as pointed out by Duncan C in the comments, and as should have been in the original answer)
A good starting point is just to return true from this method, as then all the user input will be reflected in the text field. If you need to be more specific about what edits you allow you can introduce that logic later.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Backspace handled
guard !string.isEmpty else {
return true
}
return true
}

UITextField shouldChangeCharacters in swift is not working for the first letter entered

I have a textfield population phone number. When i am entering phone number i am checking validation for a invalid phone number. i am using delegate method "textfield should change characters".It is working fine but it is not working for the first letter entered by the user.
extension phoneCell: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
validateInput(of: textField)
return true
}
Can any one help me to resolve this?
If you noticed then shouldChangeCharactersIn has a return type Bool.
What it means is that when a user presses a key on the keyboard, you'll get a callback by this delegate before even registering that character in the textfield.
Now if you return true, that pressed character will be reflected in the textfield if you return false, input will be discarded.
So for first time your string.count will be 1 but your textfeild.text.count will be 0.
Looking at your validation code I will suggest you add an IBAction on your textfeild for editing changed[here].
What does your validation function do? Why are you returning true by default?
shouldChangeCharactersIn should return the result of your validation function.

UITextfield letting only one decimal

How to let user insert only one decimal in the textfield in language Swift.There are quite a lot of help for this on the site,but none of them work as they are all Swift 1 code. Thank you in advance.
First, you should make your class conform the to the UITextFieldDelegate protocol like this:
class YourViewController: UIViewController, UITextFieldDelegate
Then, you should set the delegate of your textField to self:
yourTextField.delegate = self
Finally, whenever the content of your UITextField changes, this delegate method will be called, so add it to your view controller.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//handle changes here
}
If you want only one character to appear you could disallow changes to the content of your UITextField when it is already filled:
if yourTextField.text?.characters.count > 0 {
return false
}
return true
If you only want to allow decimal characters you could check for this too, and add the condition to the if query.

Making it so the user cannot press the button unless something is entered in the textfield

How would I make it so a button that uses the segue to send you to the next view controller not work if nothing is entered in the text field above it?
Add this to the viewdidload, replacing textfieldVerb with the name of your textbox, and nextVerbOutlet with the name of your button (as a outlet)
self.textFieldVerb.addTarget(self, action: "textFieldChanged:", forControlEvents: .EditingChanged)
self.textFieldVerb.addTarget(self, action: "textFieldChanged:", forControlEvents: .EditingChanged)
nextVerbOutlet.enabled = false
and then add this replacing textfieldVerb with the name of your textbox, and nextVerbOutlet with the name of your button (as a outlet). This doesn't go in the viewdidload, but under it.
func textFieldChanged(sender: UITextField) {
// simple validation
if textFieldVerb.text?.characters.count > 0
&& textFieldVerb.text?.characters.count > 0 {
self.nextVerbOutlet.enabled = true // re-enable your button
}
}
You could implement optional func textField(_ textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool of the UITextFieldDelegate. It will get triggered every time user enters or deletes character in the text field. You can examine the contents there and enable/disable your button from there appropriately.
You could check for the content of the TextField:
if myTF.text != "" || myTF.text != nil {
//TextField contains something
//enable button
//segue to next ViewController
} else {
//TextField empty
//disable button
}
If you implement that into textFieldDidEndEditing() it will check each time the user is done typing.
Make sure to include the UITextFieldDelegate in your class like:
class myClass: UIViewController, UITextFieldDelegate {...}
Hope that helps :)
Implement the UITextFieldDelegate protocol and set your VC as the delegate.
Then implement the
func textField(_ textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String)
method of that protocol.
You use this method to detect an empty string. You can choose to be thorough and handle copy/paste in which case you will need to calculate the value of the new string after the replacement using stringByReplacingCharactersInRange, or you can choose to not handle copy paste and just check that range.location > 0.
Based upon the the above you can set the enabled property of the button accordingly.

TextField delegate shouldChangeCharactersInRange

Why doesn't the shouldChangeCharactersInRange update the textfield right away. It is 1 delayed by one character.
For example, download this file: https://www.dropbox.com/s/goljs3d6lcxutxy/UITextField%20Tutorial.zip?dl=0
add the following code to
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
method
print(textField.text)
see how it is delayed by one character. I want it to be updated as I type the text not one delayed.
That method is asking you if it should take the replacementString and add it onto textField.text. It is called immediately after you press a key on the keyboard and before letter appears on screen.
To see what the new string will be, you'd need to to something like this.
let newText = textField.text.stringByReplacingCharactersInRange(range, withString: string)
print(newText)