TextFieldDidBeginEditing is called prematurely

I have an application in which I need to scroll up in case of showing the keyboard. to get the size of the keyboard, I log the UIKeyboardWillShowNotification event as follows:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window] 

This works, the problem is that it is called after calling textFieldDidBeginEditing . Thus, I can’t get the actual size of the keyboard, but only after the field is already in edit mode, which damages the entire purpose of recording this event in the first place. I am sure that I called UIKeyboardWillShowNotification , not UIKeyboardDidShowNotification , although changing these two gives the same results: the first call was made using the delegation method, and only then the notification method. Any idea on how to do this? I am currently hard-coded for size, which is very bad practice ...

+7
source share
5 answers

Can i suggest a github repository

https://github.com/hackiftekhar/IQKeyboardManager

+2
source

Here is the base class that I wrote for this use for sure. This is a subclass of UIViewController Whenever I want to implement this behavior, I just make my view controller a subclass of this base class.

By the way. You're right. textFieldDidBeginEditing is called after the keyboard appears, so you want to scroll through the keyboard callback method, as described in my class.

Also note that for this you need to embed your entire view into the scroll view and connect IBOutlet to the scroll view to it.

If you are not using the story panel, remove the IBOutlet part and paste your view into the scroll and make the connection in code.

After that, the code is indicated here:

Header file

 #import <UIKit/UIKit.h> @interface BaseViewControllerWithKeyboard : BaseViewController @property (nonatomic, strong) IBOutlet UIScrollView *scrollView; @property (nonatomic, strong) UITextField *activeField; @end 

Implementation file

 #import "BaseViewControllerWithKeyboard.h" @interface BaseViewControllerWithKeyboard () @end @implementation BaseViewControllerWithKeyboard - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; [self registerForKeyboardNotifications]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } // Call this method somewhere in your view controller setup code. - (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } // Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWasShown:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0); _scrollView.contentInset = contentInsets; _scrollView.scrollIndicatorInsets = contentInsets; // If active text field is hidden by keyboard, scroll it so it visible // Your app might not need or want this behavior. CGRect aRect = self.view.frame; aRect.size.height -= kbSize.height; if (!CGRectContainsPoint(aRect, _activeField.frame.origin) ) { [self.scrollView scrollRectToVisible:_activeField.frame animated:YES]; } } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; _scrollView.contentInset = contentInsets; _scrollView.scrollIndicatorInsets = contentInsets; } @end 
+1
source

I opened a new project in Xcode 5, added a UITextField to the ViewController and linked its delegate.

This is my only code:

 - (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myNotificationMethod:) name:UIKeyboardWillShowNotification object:nil]; } - (void)myNotificationMethod:(NSNotification*)notification { NSDictionary* keyboardInfo = [notification userInfo]; NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey]; CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue]; NSLog(@"Rect: %@",NSStringFromCGRect(keyboardFrameBeginRect)); } 

Here is the log output:

Portraid:

  Rect: {{0, 480}, {320, 216}} 

Landscape:

  Rect: {{-162, 0}, {162, 480}} 

Edit:

Regarding textFieldDidBeginEditing called before name:UIKeyboardWillShowNotification , I really don’t understand why there is a difference if textField is in edit mode or not, but there are several ways to solve this problem.

  • saving the link to textField from textFieldShouldBeginEditing and using it inside myNotificationMethod if textFieldShouldBeginEditing was called in did.

  • Playing with a UIResponder as follows:

in textFieldDidBeginEditing β†’ Keep a link to the UIResponder and change the UIResponder to a temporary, irrelevant. in myNotificationMethod do what you want to do so that textField (which is not in \ first responder edit mode), when you are done, make it the main UIResponder .

0
source

According to Apple's documentation, UIKeyboardWillShowNotification is called immediately before the keyboard is displayed, and UITextFieldDidBeginEditing is called immediately after the text field becomes the first responder. The process of showing the keyboard starts after the text field becomes the first responder and only if the keyboard is not yet shown. This means that UIKeyboardWillShowNotification will be called after UITextFieldDidBeginEditing . Therefore, UITextFieldDidBeginEditing is not called prematurely.

If you just want to scroll up so that the text field is not hidden under the keyboard, you can simply set the scroll content offset to the y-origin of the text field in UITextFieldShouldBeginEditing or UITextFieldDidBeginEditing .

0
source

Old question, but today I came across the same question. I created a small dirty workaround that does not force me to hardcode the size of the keyboard. I just did the following in viewDidAppear (attention - Swift):

  override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) self.infoTextField.becomeFirstResponder() self.infoTextField.resignFirstResponder() } 

This calls UIKeyboardWillShowNotification , and you can get the keyboard size from the notification and save it in the property. Hope this helps someone, it worked in my case.

0
source

All Articles