Is it possible to check if a TextField has been resigned?
I have 3 TextFields, and Cycle through them with return key with (resignFirstResponder) and (becomeFirstResponder)
But is there a way to check if a field has resigned? I noticed some of my app testers don’t use return key but click manually on the fields, and that way my previous field doesn’t save data the way it should.
What’s the best way to check if a user clicked away from a TextField ? Either on to a next text field or temporary away ?
isFirstResponder Apple Docs
Returns a Boolean value indicating whether this object is the first responder.
var isFirstResponder: Bool { get }
how to use
if txtField.isFirstResponder {
// do whatever you want to
}
If you want to save data when textField change focus .. you should implement delegate method of text field
Before resigning as first responder, the text field calls its
delegate’s textFieldShouldEndEditing(_:) method. Use that method to
validate the current text.
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool
in your case yo can check which texfield ends editing
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if textField == textfield1 {
// save
}
}
Apple Docs for textFieldShouldEndEditing
Related
I am relatively new to iOS programming, and have been curious about a pretty common UITextField delegate function.
In the developer documentation for optional func textFieldShouldReturn(_ textField: UITextField) -> Bool it states:
Return Value true if the text field should implement its default
behavior for the return button; otherwise, false.
I am curious as to what the default behavior for a return button is? In what cases would I return true, or false?
If you want to hide the keyboard when the user clicks return button then
return true
otherwise default is false , the logic depends on your UX of whether you want the keyboard visible all time or not
I searched everywhere and can't seem to find anything on this. For example I want to have more then one UITextField on the same screen. If I tap on one and type in information and click return it does an action. If you tap in the second one and return the keyboard it does a different action.
Any suggestions or help would be awesome thanks!
One option is to use tags. In the example below you can select the next textfield, and only on the last one do we login. You could use cases to do whatever you'd like
//automatically move to the next field
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
let next = textField.tag + 1
// Find next responder
if let nextField = view.viewWithTag(next) as? UITextField {
nextField.becomeFirstResponder()
} else {
// Not found, so remove keyboard.
textField.resignFirstResponder()
//do the final action to login
loginAction()
}
return false
}
Since iOS 9, you can connect the “Primary Action Triggered” event of your UITextField to an action method. So you can connect each text field's “Primary Action Triggered” event to a separate action method to give the text fields different actions.
See this answer for a demo: https://stackoverflow.com/a/26288292/77567
I realized I was really over thinking it.. Took another look and saw what I was trying to do was a lot easier then I thought.. Thanks everybody who helped! (just an example below)
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if field1.resignFirstResponder() {
print("yellow")
}
if field2.resignFirstResponder() {
print("blue")
}
return (true)
}
I have two textFields and a Done button in my VC but I'm having some problems with the ending of editing.
My textFieldDidEndEditing method is called when I tap on one textField after being inside the other one, or when I tap outside the textField (because I added a tap recognizer to the parent view) but not when I tap the Done button.
And, most important (especially when I run on an actual device), the keyboard won't disappear under any of these circumstances, even though my textFieldDidEndEditing method calls resignFirstResponder().
Why isn't the keyboard dismissing? Also, is there a way to have textFieldDidEndEditing get called when I tap outside the field just automatically (without having it come from the tap recognizer)? It just seems like this should be how it works, but if I'm wrong, I'm wrong.
Here's some pertinent parts of my code.
1.Trying to dismiss the keyboard. The first part of this method works, and the value is stored (when the method is called at all, that is). At no point does the cursor disappear from the textField, nor does the keyboard get dismissed.
func textFieldDidEndEditing(_ textField: UITextField) {
if let playerName = textField.text, let playerNum = nameFields.index(of: textField) {
playerNames[playerNum] = playerName
}
resignFirstResponder()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textFieldDidEndEditing(textField)
return true
}
Also, here's a curious thing: when I set a breakpoint in textFieldDidEndEditing and debug, enter a value in one field and hit Done, it segues to the next scene, and then stops at textFieldDidEndEditing, which at this point has no effect (the values may be stored but they aren't reflected in the new scene).
2.Trying to add the tap recognizer to the done button. I don't have an outlet to the done button in my code, just out of laziness, so that's probably the best solution. But, I'm still interested in why this doesn't work. This is identical to the code that defines the tap recognizer that's working in the parent view.
func dismiss(_ sender:UITapGestureRecognizer) {
nameFields.forEach { textFieldDidEndEditing($0) }
}
override func viewDidAppear(_ animated: Bool) {
for view in view.subviews where view is UIButton {
let dismissTextField = UITapGestureRecognizer(target: self, action: #selector(dismiss(_:)))
dismissTextField.numberOfTapsRequired = 1
view.addGestureRecognizer(dismissTextField)
}
}
You need to call resignFirstResponder inside textFieldShouldReturn method instead of calling textFieldDidEndEditing.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
Also in your TapGesture method simply call endEditing(_:) with your view instead of looping through the array of textFields.
func dismiss(_ sender:UITapGestureRecognizer) {
self.view.endEditing(true)
}
Swift 5: This solution below is much easier actually.
Simply subclass your ViewController with the text fields to UITextFieldDelegate like this:
class CreateGroupViewController: UIViewController, UITextFieldDelegate {
then if you named your UITextFields: nameTextField & occupationTextField then add the following delegations to your viewDidLoad() method:
self.nameTextField.delegate = self
self.occupationTextField.delegate = self
Then simply add the generic function to your file:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
If you do it this way, then for every textField reference outlet you create, all of them will hide the keyboard after the user hits the return button no matter which textField he's typing. For each textField you add to your view, add another self.nextTextField.delegate = self line to your viewDidLoad.
Remember to test this with your iPhone/iDevice plugged into your developer computer bc XCode's simulator doesn't bring up the keyboard (bc you're normally testing using a full keyboard). Or if you've set up your testing hardware (iPhone) via WiFi you can do it that way also. Otherwise, your users will be "testing" this on TestFlight.
Is there a way to change the responder or select another textfield by pressing tab on the keyboard, in Swift?
Notes:
It's for a fill in the blank type application.
My VC creates a list of Words [Word], and each of those words has its own WordView - word.wordView. The WordView is what is displayed. WordView is a child of NSTextField.
I tried to override keydown but it doesn't allow me to type anything in the text view.
You have to connect your textField nextKeyView to the next textField through the IB or programmatically:
textField1.nextKeyView = textField2
Assuming you want to go from textView1 to textView2. First set the delegate:
self.textView1.delegate = self
Then implement the delegate method:
func textView(textView: NSTextView, doCommandBySelector commandSelector: Selector) -> Bool {
if commandSelector == "insertTab:" && textView == self.textView1 {
self.window.makeFirstResponder(self.textView2)
return true
}
return false
}
If you want some control over how your field tabs or moves with arrow keys between fields in Swift, you can add this to your delegate along with some move meaningful code to do the actual moving like move next by finding the control on the superview visibly displayed below or just to the right of the control and can accept focus.
public func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
switch commandSelector {
case #selector(NSResponder.insertTab(_:)), #selector(NSResponder.moveDown(_:)):
// Move to the next field
Swift.print("Move next")
return true
case #selector(NSResponder.moveUp(_:)):
// Move to the previous field
Swift.print("Move previous")
return true
default:
return false
}
return false // I didn't do anything
}
I had the same or a similar problem, in that I wanted to use an NSTextView field, to allow multiple lines of text to be entered, but it was the sort of field where entering a tab character would make no sense. I found an easy fix for this: NSTextView has an instance property of isFieldEditor, which is set to false by default; simply set this to true, and tabs will now skip to the next field.
what is the exact difference between textFieldDidBeginEditing and textFieldShouldBeginEditing. and i want to know in which scenario we use them(I know that they are called when we enter any thing into textfield. i want to know the exact time in which they are called when we use both in our program)
A "shouldBegin" something allows you to say NO on the return value to prohibit the action.
A "didBegin" something says it has just started to happen and you need to take whatever actions you need to do at that point in time.
A textFieldShouldBeginEditing method requests permission from the delegate to allow the textField to be edited when, say, a user taps on it.
On the other hand, textFieldDidBeginEditing is called when a textField begins editing content (i.e. right after textFieldShouldBeginEditing, if allowed).
Example: you want to make a non-editable text field, so you return NO:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return NO;
}
About textFieldDidBeginEditing:
Discussion
This method notifies the delegate that the specified text field just became the first responder. You can use this method to update your delegate’s state information. For example, you might use this method to show overlay views that should be visible while editing.
So let's say that you have a text field subclass (and you want it to be editable) that while the user edits the contents changes the graphic (example: it wants to display a different focus ring while the user types), so you use it to do these things.
if you set the tags (from Storyboard) for "username" and "password" fields to 0 and 1 respectively and then try to catch acitve field inside func textFieldDidBeginEditing, it does not work!
**func textFieldDidBeginEditing(_ textField: UITextField) -> Bool
{
activeTextField = textField
return true
}**
**func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
let value = activeTextField.tag
switch value
{
case 0:
// for username field it should execute this case
case 1:
// for password field it should execute this case
}
}**
the same function is working and providing correct results when called as #objc func textFieldDidBeginEditing, without "objc" word it is not picking the active field. I just want to know, why is so...
**#objc func textFieldDidBeginEditing(_ textField: ) -> Bool
{
activeTextField = textField
return true
}**