textFieldDidBeginEditing被过早调用

我有一个应用程序,我必须在键盘显示的情况下向上滚动。 获取键盘大小,我正在注册UIKeyboardWillShowNotification事件如下所示:

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

这是行得通的,问题在于,在调用textFieldDidBeginEditing之后调用它。 所以,我不能得到实际的键盘大小,但只有在该字段已经处于编辑模式之后,这首先破坏了注册该事件的整个目的。 我确定我已经调用了UIKeyboardWillShowNotification而不是UIKeyboardDidShowNotification ,虽然切换这两个产生相同的结果:首先调用委托方法,然后才通知通知方法。 任何想法如何扭转这种情况? 目前我是硬编码的大小,这是非常糟糕的做法…

我可以build议一个GitHub存储库

https://github.com/hackiftekhar/IQKeyboardManager

这是我为这个用途写的一个基类。它是UIViewController一个子类。每当我想实现这样的行为,我只是让我的视图控制器成为这个基类的一个子类。

顺便说一句 – 你是对的。 textFieldDidBeginEditing在键盘显示后调用,这就是为什么你想要在我的类中描述的键盘的callback方法向上滚动。

另外请注意,为了这个工作,你需要在滚动视图中embedded整个视图,并将滚动视图的IBOutlet连接到它。

如果您不使用故事板,请移除IBOutlet部分并将视图embedded到滚动视图中,然后在代码中进行连接。

之后这里说的是代码:

头文件

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

实施文件

 #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's 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 

我在XCode 5中打开了一个新项目,在ViewController添加了一个UITextField ,并连接了它的委托。

这是我唯一的代码:

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

这里是日志输出:

Portraid:

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

景观:

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

编辑:

关于在name:UIKeyboardWillShowNotification之前调用textFieldDidBeginEditing ,我不明白为什么textField处于编辑模式或者没有,但是有几种方法可以解决这个问题。

  1. 从textFieldShouldBeginEditing中保存对textField的引用,并在myNotificationMethod中使用它,如果inFieldShouldBeginEditing被触发。

  2. 像这样玩UIResponder

textFieldDidBeginEditing – >保存对UIResponder的引用,并将UIResponder更改为一个不相关的温度。 在myNotificationMethod做什么你想要做的textField(这是不是在编辑模式\第一响应者),当你完成使你的主要UIResponder

根据Apple文档,在键盘显示之前调用UIKeyboardWillShowNotification ,而在文本字段变成第一响应者之后调用UITextFieldDidBeginEditing 。 显示键盘的过程在文本字段成为第一响应者之后开始,并且只有当键盘还没有被显示时。 这意味着UIKeyboardWillShowNotification将在UITextFieldDidBeginEditing之后被调用。 所以UITextFieldDidBeginEditing不会被过早地调用。

如果您只想向上滚动以便文本字段不会隐藏在键盘下方,则可以将滚动视图的内容偏移量设置为UITextFieldShouldBeginEditingUITextFieldDidBeginEditing中文本字段的y原点。

老问题,但今天我遇到了同样的问题。 我已经build立了一个“脏”的解决方法,不强迫我硬编码的键盘大小。 我只是做了以下viewDidAppear(注意 – 斯威夫特):

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

这会触发UIKeyboardWillShowNotification ,您可以从通知中获取键盘大小并将其存储在属性中。 希望这有助于某人,它在我的情况下工作。

Interesting Posts