what is the exact difference between textFieldDidBeginEditing and textFieldShouldBeginEditing - iphone

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
}**

Related

How do I get the value of UITextField text instance property and update UITableView row whenever the user edits the UITextField text property?

How would I update a table view row as as a text field text changes? It is difficult to create a string from the arguments in textField(:shouldChangeCharactersIn:replacementString:) so that the string I create would be equal to the string value of the text property of the text field after the textField(:shouldChangeCharactersIn:replacementString:) occurs. Is there a way to use the UITextInput protocol of UITextField? I haven't found anything on stackoverflow about using the UITextInput protocol of UITextField except a question in 2012 using Objective-C that asks why he's getting a crash.
If I understand your question correctly, you want something that calls a function every time the user edits the text field. You can do this by either connecting a function via the storyboard, or use a target in viewDidLoad()
Here's how I usually use it in viewDidLoad():
textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
textField.tag = 0 //Use this to differentiate between text fields if needed
And in my textFieldDidChange function:
#objc func textFieldDidChange(_ textField: UITextField) {
String text = textField.text
//Do something else
}
I hope I understood your question correctly. You can also connect an action from the storyboard for editingChanged, similar to how you would do it for a UIButton.

Check for exiting TextField resignedFirstReponder?

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

Can I set different actions when a keyboard is returned?

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)
}

Swift: Can't get UITextField to dismiss keyboard

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.

how to avoid keyboard in textfields

I use a couple of buttons '0123456789.' (and some others) as an alternative for a keyboard. They are connected to (several) texfields. I made them all programmatically, so without storyboard. I also use UITextFieldDelegate. That works as expected, and I can input my text into the textfields.
I use the following code for my buttons:
func textFieldDidBeginEditing(textField: UITextField) {
activeField = textField
}
#IBAction func Pressed(sender: UIButton) {
if (activeField != nil) {
switch sender.tag {
case 0:
activeField!.text = activeField!.text+"0"
case 1:
The problem is that every-time I click in a textfield, the keyboard opens up too. I want to avoid that... since I made an alternative for input with the buttons. How can I get rid of the keyboard when I click in a textfield?
Just return NO from textFieldShouldBeginEditing: from the delegate you mention you are already using.
When the user performs an action that would normally initiate an editing session, the text field calls this method first to see if editing should actually proceed. In most circumstances, you would simply return YES from this method to allow editing to proceed.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if (textField == /* a text field that is using your custom layout */)
return NO;
}
[Source]
Though why don't you just use [textField setKeyboardType:UIKeyboardTypeNumberPad];
You should make your custom keypad the inputView of the textField. It will then be shown instead of the built-in keyboard.
i.e.:
textField.inputView = yourCustomKeypad;
I've made a similar input interface, using custom buttons...why not instead of a UITextField, use a UILabel to display the "8,900"(input).
Then just make the buttons manipulate the UILabel.text.