onm*_*133 10 xcode notifications first-responder ios
我有一个项目,其中包含一个UIScrollView和许多UITextField内部.
我第一次选择a UITextField,UIKeyboardWillShowNotification被称为,这很好.但每当我选择新的UITextField(键盘仍在那里),UIKeyboardWillShowNotification再次调用!!!,这很奇怪.
我还设置了一个符号断点[UIResponder resignFirstResponder],我看到它UIKeyboardWillShowNotification被调用之前和之后!
另一件事是UIKeyboardWillHideNotification只有当我点击键盘上的"完成"按钮时才会调用它
我敢肯定,不调用任何resignFirstResponder,becomeFirstResponder,endEditing任何地方.(我的意思是不要错误地打电话)
什么可能导致这个问题?
这是堆栈跟踪

onm*_*133 12
问题是我设置inputAccessoryView的UITextField,而这个原因UIKeyboardWillShowNotification,当新的被称为再次UITextField选择了
这篇文章在iOS上使用键盘解释了这一点
当我们将外部键盘连接到iPad时,会发生其他更改.在这种特殊情况下,通知行为取决于控件的inputAccessoryView属性,这是显示键盘的原因.
如果inputAccessoryView不存在或其高度等于0磅,则不会发送键盘通知.我的猜测是,这是因为在这种情况下,应用程序中不会发生视觉变化.否则,所有通知都按预期运行 - 这意味着在键盘显示或隐藏在正常(未取消停靠或拆分)状态的大多数情况下,它们将被发送.
每当UITextField选择new时,操作系统需要再次计算键盘的帧,并发布以下通知
UIKeyboardWillChangeFrameNotification
UIKeyboardWillShowNotification
UIKeyboardDidChangeFrameNotification
UIKeyboardDidShowNotification
Run Code Online (Sandbox Code Playgroud)
当TextField失去其第一个响应者状态时,这同样适用
请注意,使用相同的 View inputAccessoryView将UIKeyboardWillShowNotification仅导致调用一次
要解决此问题,我使用以下代码取消UIKeyboardWillShowNotification回调,如果键盘的框架没有更改.
func keyboardWillShow(notification: NSNotification) {
let beginFrame = notification.userInfo![UIKeyboardFrameBeginUserInfoKey]!.CGRectValue()
let endFrame = notification.userInfo![UIKeyboardFrameEndUserInfoKey]!.CGRectValue()
// Return early if the keyboard's frame isn't changing.
guard CGRectEqualToRect(beginFrame, endFrame) == false else {
return
}
...
}
Run Code Online (Sandbox Code Playgroud)
对于Swift 3/4:
func keyboardWillShow(notification: Notification) {
let userInfo = notification.userInfo!
let beginFrameValue = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)!
let beginFrame = beginFrameValue.cgRectValue
let endFrameValue = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)!
let endFrame = endFrameValue.cgRectValue
if beginFrame.equalTo(endFrame) {
return
}
// Do something with 'will show' event
...
}
Run Code Online (Sandbox Code Playgroud)
总的来说,我发现很多事情都会导致虚假UIKeyboardWillShow和UIKeyboardWillHide通知。我的解决方案是使用一个属性来跟踪键盘是否已经显示:
func keyboardShow(_ n:Notification) {
if self.keyboardShowing {
return
}
self.keyboardShowing = true
// ... other stuff
}
func keyboardHide(_ n:Notification) {
if !self.keyboardShowing {
return
}
self.keyboardShowing = false
// ... other stuff
}
Run Code Online (Sandbox Code Playgroud)
这些守卫准确地阻止了虚假通知,之后一切就都很好了。而且该keyboardShowing属性可能因其他原因而有用,因此无论如何它都是值得跟踪的。
| 归档时间: |
|
| 查看次数: |
15938 次 |
| 最近记录: |