UIKeyboardDidShowNotification多次调用,有时键盘尺寸不正确

时间:2014-12-23 05:56:20

标签: ios uikeyboard nsnotification

每当键盘出现/更改时,我都会尝试在键盘上方移动UITextView。假设我显示英文键盘,然后直接切换到中文键盘(比标准英文键盘高)。在这种情况下,我的文本视图总是显得太高(肉眼看来,文本视图被中文键盘“输入附件视图”的大小错误地偏移。我发布的图片却缺乏声誉所以:))。当我的应用程序收到UIKeyboardDidShowNotification(使用UIKeyboardFrameEndUserInfoKey获取高度)时,我正在调整我的文本视图位置,经过一些调查多次调用UIKeyboardDidShowNotification,通常键盘尺寸不正确(我已经NSLogged userInfo字典)。我在ViewWillAppear中注册我的键盘通知,并在ViewWillDisappear中取消注册。我无法确定导致此通知多次触发的原因;我的理解是,只有在键盘完成显示后才会触发此通知一次。另外需要注意:我在响应UIKeyboardDidShowNotification的方法中使用了NSLogged“self”,它实际上始终是相同的View Controller Object。

然而,即使多次触发此通知,我仍然不明白为什么某些通知的键盘高度会有所不同。其中一个通知始终具有正确的高度,但是当它不是最后一个通知时,文本视图最终会出现在错误的位置。任何有关如何进一步排除故障的见解都将非常感激!

编辑:我测得的越多,特别是中文键盘的问题就越多。每当我将键盘从英文切换到中文时,我得到三个UIKeyboardWillShowNotifications:

2014-12-24 22:49:29.385 Example[1055:421943] info dictionary: {
UIKeyboardAnimationCurveUserInfoKey = 0;
UIKeyboardAnimationDurationUserInfoKey = 0;
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 252}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 460}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 442}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 352}, {320, 216}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 316}, {320, 252}}";
}
2014-12-24 22:49:29.408 Example[1055:421943] info dictionary: {
UIKeyboardAnimationCurveUserInfoKey = 0;
UIKeyboardAnimationDurationUserInfoKey = 0;
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 442}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 460}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 316}, {320, 252}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 352}, {320, 216}}";
}
2014-12-24 22:49:29.420 Example[1055:421943] info dictionary: {
UIKeyboardAnimationCurveUserInfoKey = 0;
UIKeyboardAnimationDurationUserInfoKey = 0;
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 288}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 442}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 424}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 316}, {320, 252}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 280}, {320, 288}}";
}

第一个具有正确的结束高度:252。然而,接下来的两个在216和288处是不正确的。这可靠地发生。

以下是一些片段,用于演示我如何管理订阅通知:

-(void)viewWillAppear:(BOOL)animated {

       [super viewWillAppear:animated];


       [self registerForKeyboardNotifications];


}

-(void)viewWillDisappear:(BOOL)animated {
       [super viewWillDisappear:animated];

       [[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:UIKeyboardWillHideNotification
                                                object:nil];
       [[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:UIKeyboardDidShowNotification
                                                object:nil];

}

- (void)registerForKeyboardNotifications {



      [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidHide:)
                                             name:UIKeyboardWillHideNotification object:nil];

      [[NSNotificationCenter defaultCenter] addObserver:self      
                                         selector:@selector(keyboardDidShow:)                                       
                                             name:UIKeyboardDidShowNotification object:nil];
}

4 个答案:

答案 0 :(得分:6)

如果您在模拟器上使用Cmd + K快捷键来显示/隐藏键盘,则可能会多次调用它,因为它不会将文本字段作为第一响应者辞职。

如果您改为使用键盘的 .select("tr:nth-of-type(6) a[href^=?Company]")) 按钮,那么它会做正确的事并辞职。

答案 1 :(得分:4)

主要原因是您的通知被多次调用。例如,在swift中,如果你在viewWillAppear方法中有了NSNotificationCenter.defaultCenter()。addObserver(xx" keyboardWillShow" xx),如果你在视图之间往返,那么它将导致有多个观察者相同的" keyboardWillShow"。相反,您应该考虑将addObserver调用移动到" viewDidLoad()"方法。或者,您可以在视图显示/消失时注册/取消注册观察者。

答案 2 :(得分:0)

- (void)keyboardDidAppear:(NSNotification *)note {
    CGSize keyboardSize = [note.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
    textView.contentInset = contentInsets;
    textView.scrollIndicatorInsets = contentInsets;
}

- (void)keyboardWillBeHidden:(NSNotification *)note {
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    textView.contentInset = contentInsets;
    textView.scrollIndicatorInsets = contentInsets;
}

解决方案来自Apple的官方解决方案here,就像曹说的那样。

答案 3 :(得分:0)

在我的情况下,我在ViewWillAppear中注册我的键盘通知,并在ViewWillDisappear中取消注册。但是,它会导致多次触发UIKeyboardDidShowNotification处理程序。好像取消注册方法不起作用,因此,每次出现视图时,Observer for UIKeyboardDidShowNotification加1.然后,你触摸UITextField,多个Observer会被通知,处理程序会一次又一次被触发。

因此,您必须在ViewDidLoad中注册键盘通知,而不是取消注册。就像这个page中提到的Apple一样,

  

//在视图控制器设置代码中的某处调用此方法。

我认为'setup'表示ViewDidLoad.And在处理键盘通知代码列表中,没有ViewWillDisappear。

这是我的键盘通知处理程序,它可以正常工作。

   func keyboardWillShow(notification: NSNotification) {
    let userInfo = notification.userInfo!
    let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
    debugPrint("Before",NotifyView.frame)
    NotifyView.frame.offsetInPlace(dx: 0, dy: -keyboardHeight)
    debugPrint("After",NotifyView.frame)
}
func keyboardWillHide(notification: NSNotification) {//Do Nothing
}