Why textFieldShouldReturn is still working when i return false? - ios

I am hiding keyboard on return key pressed by implementing function textFieldShouldReturn and calling resignFirstResponder() inside this function. It works perfectly but when I return false in this function, still then keyboard is hiding. Now here I do not understand that what is use of returning true or false if keyboard is hiding in both case?

The keyboard is being dismissed due to the call to resignFirstResponder. It has nothing at all to do with the return value of textFieldShouldReturn.
In my experience, the return value of textFieldShouldReturn almost has no use. In the vast majority of cases it makes no difference whether you return true, or false.
I return false in all my uses of testFieldShouldReturn. If you return true and your implementation of textFieldShouldReturn sets the first responder to a UITextView, the text view ends up getting the newline added to it. Returning false from textFieldShouldReturn ensures this won't happen. But this was based on experience with iOS 4 or 5 a few years ago. I don't know if that still happens with the latest versions of iOS.

The return value from textFieldShouldReturn answers a different question. If the text field has an action for the control event editingDidEndOnExit, that will cause the keyboard to dismiss unless textFieldShouldReturn is implemented to return false.

I have tried that wether true or false, the keyboard do dismiss, here is the code:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
The keyboard do dismiss or not depends on "textField.resignFirstResponder()",
if you delete it, the keyboard does no longer dismiss, whether true or false.

It's been a long time since I worked on Native iOS. Nearly 2 years. I've just picked up swift 5 and working through the forgotten and new parts right from the basics. Here's what i have observed.
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if searchTextField.text != "" {
return true
}
searchTextField.placeholder = "Type Something"
return false
}
Here when I press the return key without typing a single letter in it, Keyboard does not dismiss. Rather the placeholder text changes to notify user to type something. The magic of returning false from textFieldShouldEndEditing.
If I press the same return key after entering at the very least a single character, it simply dismisses the keyboard. Courtesy of returning a true from the same textFieldShouldEndEditing.
I also didn't observe any difference when I placed textField.resignFirstResponder() regardless if I return true or false.
Conclusion:
true dismisses the keyboard. false stops the keyboard from dismissiong.

Related

How to move one text field to another using keyboard return key in swift3 ios

By this img with done btn to move at next textfield (https://i.stack.imgur.com/cDHlh.jpg)
I doubt if you can do that with the 'Done' button, but you may achieve that with the return key by
Make your class a UITextField Delegate
class VC: UIVIewController, UITextFieldDelegate
In your ViewDidLoad method do this -
textField1.becomeFirstResponder()
So that when user comes in this screen the 1st textfield will directly become active(not the right word but using this word for lack of better alternative)
And when you need it to move to the next textfield when he presses return,
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField1.resignFirstResponder()
if (textField == textField1){
textField2.becomeFirstResponder()
}
else if (textField == textField2){
textField3.becomeFirstResponder()
}
return true
}
You may use a switch case too in the above delegate method. And as mentioned in the comment in the question, do go through the link and know how to properly ask questions, giving as much detail as possible.

The caret disappears or won't show up in UITextField

I'm having trouble with the caret of UITextfields.
Whenever I tap on the textfield the caret doesn't show, but otherwise the textfield is working properly. The problem is similar to the problem described here (already tried the solution written there as well).
I noticed that whenever I load a viewcontroller and tap on a textfield (or programatically make it the first responder) it does show a caret, but as soon as I tap another textfield or make a textfield resign its first responder status no textfield will show its caret anymore (unless I go back and reload the viewcontroller again).
Got no clue as of why this is happening. I am using a custom font throughout the app. But I'm not sure if that's what making the caret disappear, as I've used custom fonts before with no problem whatsoever.
EDIT:
I think I've at least found why the problem occurs. It is related to me overriding the becomeFirstResponder and resignFirstResponder.
My code looks like:
extension UITextField {
open override func becomeFirstResponder() -> Bool {
let willBecomeResponder = super.becomeFirstResponder()
if willBecomeResponder {
backgroundColor = .red
layer.borderColor = .blue
}
return willBecomeResponder
}
open override func resignFirstResponder() -> Bool {
let willResignResponder = super.resignFirstResponder()
if willResignResponder {
backgroundColor = .blue
layer.borderColor = .red
}
return willResignResponder
}
}
Overriding those methods in the extension makes the caret disappear.
I'm thinking this most likely happens because UITextField itself does some...'caret-management' in it's own implementation of those methods.
More so because even return super.becomeFirstResponder() and no custom code in the overridden method makes the caret disappear.
My question therefore is; how can one solve this problem without making a custom UITextField subclass?
Calling super obviously just calls the UIResponder's implementation, but the docs specifically mention:
becomeFirstResponder()
You can override this method in your custom responders to update your object's state or perform some action such as highlighting the selection. If you override this method, you must call super at some point in your implementation.
So I need to call super I guess.
Alright I solved my problem by overriding isFirstResponder and altering the textfield based on the super.isFirstResponder there.
Looks like:
open override var isFirstResponder: Bool {
get {
let responder = super.isFirstResponder
backgroundColor = (responder) ? .red : .blue
layer.borderColor = (responder) ? .blue : .red
return responder
}
}
I did noticed a lot of calls being sent to isFirstResponder, so maybe this isn't the most efficient way (if altering the textfield is a heavy op).

How to find out why a UITextField ended editing?

I have a UITextField that can be set into editing mode.
Normally, editing is ended by entering „Done“ on the keyboard.
This calls textFieldDidEndEditing(_ textField: UITextField), where some housekeeping happens.
In rare cases, however, an alert is shown that the user entered a geofence. If the text field is then in editing mode, it resigns first responder status since the alert view becomes first responder, and textFieldDidEndEditing(_ textField: UITextField) is also called. When the alert is dismissed, the first responder status of the text field is restored.
The problem:
I have to distinguish both cases:
If the text field ends editing because of a Done on the keyboard, housekeeping should happen.
If it ends editing because an alert was shown, housekeeping must not be done.
So, how can I distinguish both cases?
I tried to use the delegate function
textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason)
where reason may be cancelled or committed, both in both cases the reason is committed.
You could use textFieldShouldEndEditing and assuming you can identify that the geofence has been triggered, return false, which will leave the textField in edit mode, otherwise return true, and the housekeeping can begin
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool
{
// assuming you take the same action for all TextFields
// assume geoFenceHasBeenTriggered is a class-variable true / false
return !geoFenceHasBeenTriggered
}

iOS hiding keyboard on "Return" press, resignFirstResponder vs endEditing

I was searching for hiding the iOS keyboard when you press "return", and about half the answers are to use self.view.endEditing(true) and the other half textField.resignFirstResponder(). Is one a better way than the other?
For reference or anyone coming here from Google or something, you need to add UITextFieldDelegate to your class inheritance, add self.<your_TF_var_name>.delegate = self in viewDidLoad(), then make a function
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
//OR
textField.resignFirstResponder()
return true
In this case, it doesn't really matter which you use though technically, using textField.resignFirstResponder() is more efficient because you already know that is the text field you need to resign.
The call to self.view.endEditing(true) is going to have to figure out what the current first responder is and then call resignFirstResponder on it.
My general rule of thumb is to use resignFirstResponder if you have a reference to a specific view you wish to resign. And use endEditing if you don't and you just want the current first responder to be resigned.
On a side note, you should return false from textFieldShouldReturn in either case. There is an edge case where returning true can lead to a newline being added to a UITextView after resigning the UITextField. So as a rule I always return false.

Why call method to resignFirstResponder from textFieldShouldBeginEditing?

I am trying to understand delegate methods in general, and specifically how to dismiss a UIDatePicker that popovers from a text field.
According to the documentation, textFeildShouldBeginEditing returns true 'if an editing session should be initiated; otherwise, false to disallow editing.'
Why would I then tell the app to resignFirstResponder, which is meant to hide the keyboard / date picker (as in several examples on stackoverflow and noobie tutorials)?
What I don't understand is: if it should begin editing, why then hide the input devise? Obviously, I am misunderstanding one or both concepts.
func resign() {
dobTextField.resignFirstResponder()
nameTextField.resignFirstResponder()
println("resign gets printed, but the date picker is still visible!?!")
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if (textField === dobTextField) {
resign() // but should begin editing, oder?!?
}
In the examples you cite, the textField is being used to display a date. When the user selects this field, the app designers want the UIDatePicker to be displayed instead of the keyboard. Hence they call resignFirstResponder to hide the keyboard. At the same time, they display the date picker.
ResignFirstResponder will not hide the date picker, so the "input device" (for this field) will still be available.
Also, note that in one case the developer has used textFieldShouldBeginEditing, and returns false because they are providing the date picker. In the other case the developer uses textFieldDidBeginEditing (which has no return value).
you should resign only the textfield not affected:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == dobTextField {
nameTextField.resignFirstResponder()
} else if textField == nameTextField {
dobTextField.resignFirstResponder()
}
return true
}
this way you are resiging first responder only on the textfields that should not currently be edited. this helps if for some reason you accidentally have 2 textfields (or more) assigned first responder causing conflicts with multiple keyboards/datepickers and such.

Resources