In my app, on registration screen, I have tableView which containes UITextField in each cell and Submit button in a footer. Everything works fine except when I enter value in the last TextField and hit submit button (Without resigning a keyboard). My function does not show a value because value is only entered when text editing is ended. I am using Delegate to get a value.
My code is:
In customcell.m:
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ([textField.text length] >0) {
[self.cellImageview setImage:editImage];
}
else{
[self.cellImageview setImage:defaultImage];
}
[_delegate signUpTableCell:self didUpdateValue:textField.text inTextField:textField];
}
In my viewController:
-(void)signUpTableCell:(SignUpTableCell *)cell didUpdateValue:(NSString *)value inTextField:(UITextField *)textField {
NSLog(#"cell:%# value: %# textfield value:%# ", cell, value, textField.text);
[registerDictionary setValue:value forKey:textField.placeholder];
NSLog(#"registerDictionary:%#", registerDictionary);
}
Problem:
Last textField value is nil when I click on submit button, probably because
-(void)signUpTableCell:(SignUpTableCell *)cell didUpdateValue:(NSString *)value inTextField:(UITextField *)textField
does not get a call unless textField ends editing. If I click in empty place and resign a keyboard it works just fine. Is there a work around this problem?
Did you try to manually call resignFirstResponder() when clicking on the button?
Add below code to in submit button :
[self.view endEditing:yes];
or use
[self.yourTableview.scrollView endEditing:yes];
Fixed it by making few changes in my code. I had used [self.view endEditing:yes]; after I get values from registerDictionary . Stupid of me.
Related
I have two instances of a UITextField. The returnKeyType of the first text field is UIReturnKeyNext, and the returnKeyType second text field is UIReturnKeyDone. Based of this SO answer, I'm trying resign the first responder of the first text field when the 'Next' button is clicked, and then have the second text-field become the first responder. When the 'Done' button is clicked on the second text-field, the first responder is resigned, and the keyboard disappears.
Below is my code for this:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == _textFieldOne){
[_textFieldOne resignFirstResponder];
[settingsDictionary setObject: _textFieldOne.text forKey:#"TextFieldOneInfo"];
[settingsDictionary stringValueForKey:#"TextFieldOneInfo"];
[self postNotificationSettingsUpdate:settingsDictionary];
didTestPostNotificationSettings = YES;
[_textFieldTwo becomeFirstResponder];
}
if (textField == _textFieldTwo){
[_textFieldTwo resignFirstResponder];
}
return YES;
}
When the 'Next' button is clicked, the first text-field successfully resigns the first responder, and the second text-field does become the new first responder. However, the second text-field then immediately seems to resign it's first responder status, before the 'Done' button is clicked.
Can anyone tell me why the second text-field is resigning it's first responder status before it's 'Done' button is clicked? Thank you!
EDIT I've narrowed down the problem to the following line of code:
[self postNotificationSettingsUpdate:settingsDictionary];
When it's commented out, text field return-button actions behave as expected.
You don't need to call resignFirstResponder if you want switch textFields. I have successfully tried this:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == _textFieldOne){
[_textFieldTwo becomeFirstResponder];
}
else if (textField == _textFieldTwo){
[textField resignFirstResponder];
}
return YES;
}
After some digging, I believe I found a solution.
The specific offending line of code is below:
[self postNotificationSettingsUpdate:settingsDictionary];
which calls the method below:
- (void)postNotificationSettingsUpdate:(NSDictionary *) updateDict {
[self.dataCache setUserNotificationSettings:updateDict];
}
...which sends the the dictionary information over a network connection.
These text views are stored in a UITableView row. What appeared to me to be happening was that when this method was being called, it reloaded the view. The solution was to add calls to [tableView beginUpdates]; and [tableView endUpdates]; at the beginning and end of
- (BOOL)textFieldShouldReturn:(UITextField *)textField.
After doing that, the second-text field would become the first responder when the 'Next' button of the first-text field was selected, and would resign it's first responder status when the 'Done' button was selected.
I have a scroll view which contains a UITextField and a UITextView. The UITextField return key is "Next" and when this is pressed I call [myTextView becomeFirstResponder]; A random new line is inserted into my textview so I start on the second line. How do I avoid this?
Also important to note that this does not happen when I tap directly on the UITextView rather than tapping the next key.
Thanks in advance!
One solution to solve this is when you implement the textFieldShouldReturn: delegate method, be sure to return NO, and not YES. By returning NO, the newline isn't passed on to the text field.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
// move to next field or whatever you need
[myTextView becomeFirstResponder];
return NO;
}
Okay, this behaviour is due to a bug in iOS when becoming firstresponder within same run loop by using next button. To over come this you should do this manually.
First resign first responder from a textFied, and then make textView as a first responder. like this. Implement this delegate method.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
[textView performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
return YES;
}
Similar idea to performSelector, but using asynchronous dispatch queue (Swift 4 version):
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
DispatchQueue.main.async {
self.myTextView.becomeFirstResponder()
}
return true
}
I have a few UITextFields (within UITableViewCells) on my UIView with a "Save" UIButton. I want to do some basic validation on the UITextFields when the user clicks the "Save" button.
I have overridden textFieldDidEndEditing to save each of my UITextField data to an instance variable; however, if a user clicks the save button before either clicking the "Return" button of the UIKeyboard or clicking on another UITextField the data in my last UITextField is never saved to my instance variable and validation always fails.
I am looking for a way to trigger an "onBlur" (I know that's a JS thing)-type event to save my string in UITextField to my instance variable.
I've looked through the UITextFieldDelegate Protocol and I do not see anything like this.
Is there a method I may be missing?
to trigger textFieldDidEndEditing on your UITextField, you will need to call
[_txt resignFirstResponder];
were _txt is your UITextField
Please note that if you dont have a reference to _txt and you need to find the first responder in order to resign it
You could use the solution from this question Get the current first responder without using a private API
Then instead of calling
[_txt resignFirstResponder];
you would call
[self.view findAndResignFirstResponder];
Try this
// if we encounter a newline character return
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// enter closes the keyboard
if ([string isEqualToString:#"\n"])
{
[textField resignFirstResponder];
return NO;
}
return YES;
}
which will trigger
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
// Call webservice
return YES;
}
I have a strange problem with the iOS Keyboard.
In my app, I am using UITextFields inside some UITableViewCells. I want to dismiss the keyboard if the current textfield loses its focus.
This is what I've done so far:
Set up the <UITextFieldDelegate> and add [textField resignFirstResponder] to textFieldDidEndEditing:
-> textFieldDidEndEditing gets called, but the keyboard stays.
Added all TextFields to an array, looped through all objects and call resignFirstResponder
-> No effect
Called [self.tblView endEditing:YES] inside textFieldDidEndEditing.
-> Keyboard didn't disappear.
But dismissing the keyboard by using the Done-Button works perfectly (using textFieldShouldReturn)
What am I doing wrong?
Edit: I've made a video of my problem: http://www.youtube.com/watch?v=Zuz5rCv2GCo
try implementing following:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[textField becomeFirstResponder];
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[self resignFirstResponder];
}
my objective simply to save text on UITextField after user click done button on keyboard. I could either do this in extFieldShouldReturn or textFieldDidEndEditing: does it make any difference ? or there a better approach ?
Thanks!!
textFieldShouldReturn is only called if the user presses the return key. If the keyboard is dismissed due to some other reason such as the user selecting another field, or switching views to another screen, it won't be but textFieldDidEndEditing will be.
The best approach is to use textFieldShouldReturn to resign the responder (hide the keyboard) like this:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
//hide the keyboard
[textField resignFirstResponder];
//return NO or YES, it doesn't matter
return YES;
}
When the keyboard closes, textFieldDidEndEditing will be called. You can then use textFieldDidEndEditing to do something with the text:
- (BOOL)textFieldDidEndEditing:(UITextField *)textField
{
//do something with the text
}
But if you actually want to perform the action only when the user explicitly presses the "go" or "send" or "search" (or whatever) button on the keyboard, then you should put that handler in the textFieldShouldReturn method instead, like this:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
//hide the keyboard
[textField resignFirstResponder];
//submit my form
[self submitFormActionOrWhatever];
//return NO or YES, it doesn't matter
return YES;
}