I have a UITextField with a return key type of Done, and I've set the delegate to resign first responder status when the return button is tapped. I've also set an editingChanged action to let me know when the user edits the text. But it seems like it isn't being called in the following context.
Say the user has entered "Pizzs" into the text field. The editingChanged action is triggered and it says the text field's value is "Pizzs". Meanwhile, "Pizza" comes up as a suggestion in the keyboard suggestion bar. If they hit the space bar, the autocorrection is accepted and the editingChanged event is called, with the new text "Pizza ". But if they hit Done then the keyboard is dismissed, the text is changed to "Pizza" in the UITextField, but editingChanged is never called.
This is a bug, right? Should I report it to Apple? Or is this expected behavior because the text is being changed programmatically rather than by the user? And can anyone think of a good workaround?
You should use .allEditingEvents for this case.
textField.addTarget(self, action: #selector(didChangeText(_:)), for: .allEditingEvents)
I had the same issue, and worked around it by implementing the UITextFieldDelegate method textFieldShouldReturn(_ textField: UITextField) -> Bool, and doing the same thing there that I was doing in my editingChanged event handler.
So, I basically did this:
textField.addTarget(self, action: #selector(textFieldEditingChanged(_:)), for: .editingChanged)
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
processText()
return false
}
#objc func textFieldEditingChanged(_ textField: UITextField) {
processText()
}
func processText() {
// Process text here
}
Related
I'm trying to implement a search field where you type in some characters to show "possible searches". In the beginning there is a small text underneath the textbox that says "make sure to capitalize letters". This is just a UILabel. I want to make this label "disappear" when the user STARTS to type. But if the user backspaces enough to remove all text - I want the label to re-appear again.
The textbox is just made from UITextField.
This is all stored in a view.
Does anyone have an idea of how to implement something like this?
You Can do it using add a target to your textFiled with a selector like this
add this target to ur viewDidLoad method
yourTextFiled.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)
create selector method like this below your viewDidLoad Method and set if textfield.text.isEmpty than label is hidden like this
#objc func textFieldDidChange(_ textField: UITextField) {
if textField.text!.isEmpty {
label.isHidden = false
} else {
label.isHidden = true
}
}
Hope you get your desire thing !
You can do this by the textfield delegate method shouldChangeInCharacter and check when textfield is empty set the label isHidden property to false otherwise too true.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text {
if text.isEmpty {
label.isHidden = false
}
else {
label.isHidden = true
}
}
return true
}
Hope this will help you. Happy coding!
I'm learning Swift by making a times tables app, which simply creates random times tables and asks the user to type the answer in a UITextField.
I'd like the user to be able to tap the return key and have the text field clear their previous answer and have the keyboard remain in view. I've already set up the other behaviour I want, it's just I can't seem to find any similar questions to figure out how to clear, and do all this when there return key is tapped.
Here's the code I have so far, which works when dismissing the keyboard, and doesn't clear the field.
Many thanks!
#IBAction func answerTyped(_ sender: UITextField) {
/* Clear the text field*/
questionNumber += 1
attempted += 1
markQuestion(answer: answer)
newQuestion(awardLevel: currentLevel, questionNumber: questionNumber)
}
If you want the textField to be cleared on tapping return button you can use the textFieldShouldReturn delegate.
func textFieldShouldReturn(_ textField: UITextField) -> Bool { //delegate method
textField.text = "" // Clears text
//Do other things that you want to do when user taps return button
return true
}
Note that this wont dismiss the textField like how you asked and usually users are used to dismissing their textField using return. So if you ask me this is not good UX. And you need to have a mechanism for the user to dismiss the keyboard if needed like tap outside to dismiss or something. So i hope you have that sorted out.
Your viewController should have implemented the UITextFieldDelegate for this method work.
class YourViewController: UITextFieldDelegate {
var textField: UITextField! //Using IBOutlet or whatever
func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
}
}
you will need to make something, likely your view controller containing this text field into a uitextfieldelegate, then add the necessary delegate functions.
I think the function you want is TextField:DidEndEditing:Reason https://developer.apple.com/documentation/uikit/uitextfielddelegate/2352220-textfielddidendediting
Or you can just use
func textFieldShouldReturn(_ textField: UITextField) -> Bool { //delegate method
textField.resignFirstResponder()
return true
}
which is called every time user hits the return key. You would need to add your logic to clear the contents before the returns.
I have a UITextField that holds the text: "Username". I want to erase the user name once the user has selected the text field for editing.
Is there a better way than using the selector method?
Here is the method I'm currently using, but it doesn't seem to be working.
usernameTextField.addTarget(self, action: #selector(selectedUsernameField), for: .editingChanged)
func selectedUsernameField(sender: UITextField){
print("selectedUsernameField")
usernameTextField.text = ""
}
I this case you should set the placeholder for usernameTextField.
usernameTextField.placeholder = "UserName"
It will disappear as user will start typing that's what you want.
You can use this function:
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == usernameTextField{
textField.text = ""
}
}
It is called when the text field begins editing.
Although to use it you will need to make your class a UITextFieldDelegate
and also say:
usernameTextField.delegate = self
in viewDidLoad.
New to Swift and making a simple to-do app.
I am trying to get it so that when a UI TextField is clicked on, a certain button should be hidden. It's only when the user presses enter after typing in a task that the button should appear.
I have an IBAction set up for my text field to hide the UIButton when it is clicked on like so, but it doesn't work:
#IBAction func textFieldClicked(_ sender: Any) {
self.cellButton.isHidden = true
}
And I have set up my textfieldshouldreturn function when the user presses enter like so:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.cellButton.isHidden = false
self.cellButton.isUserInteractionEnabled = true
textField.resignFirstResponder()
return true
}
Does an IBAction for text field only respond when enter is pressed? I tried messing with flags but that didn't work either.
Any help is appreciated.
You don't need an IBAction for this. Instead, implement another UITextFieldDelegate method - textFieldDidBeginEditing.
func textFieldDidBeginEditing(_ textField: UITextField) {
self.cellButton.isHidden = true
}
This delegate is called when a text field becomes the first responder.
On a slightly unrelated note, it's best to return false instead of true from your textFieldShouldReturn method.
Please, use delegates method textFieldDidDeginEditing and hide button.
I have problem with add a Tap Gesture to my UITextField. Below code:
#IBAction func hanldeTap(recognizer: UITapGestureRecognizer) {
println("works")
}
This action is associated with Tap Gesture Recognizer. In my TextField I have defined gestureRecognizer in OutletCollections. In my guess it should works. In described configuration gesture works e.x. for button or custom view.
Can you tell my what could go wrong and how can I fix this?
UITextField has delegate methods, you might want to consider implementing those. Or just add action event to your textfield.
For example in viewDidLoad
textField.addTarget(self, action:Selector("textDidBeginEditing"), forControlEvents: UIControlEvents.EditingDidBegin)
Then implement this:
func textDidBeginEditing(sender:UITextField) -> Void
{
// handle begin editing event
}
If you set the textfields delegate, you can use;
optional func textFieldDidBeginEditing(_ textField: UITextField)
or
optional func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool
etc
textField.addTarget(self, action:#selector(textDidBeginEditing), for: UIControl.Event.editingDidBegin)
Swift 4.2
Adding to the accepted answer
Don't forget to add '#' before selector (with small s) i.e. #selector
textField.addTarget(self, action: #selector(textDidBeginEditing), for: UIControl.Event.editingDidBegin)
And do add #objc before the function. like
#objc func textDidBeginEditing(sender:UITextField) -> Void