意外地发现零,而解包可选值keyboardWillShow

我有下面的代码在keyboardWillShowNotification被调用时运行:

func keyboardWillShow(_ notification: Notification) { //ERROR IN THE LINE BELOW keyboard = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue animaton = (notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as AnyObject).doubleValue UIView.animate(withDuration: 0.4, animations: { () -> Void in self.scrollView.frame.size.height = self.scrollViewHeight - self.keyboard.height }) } 

我在第二行发生错误,说: unexpectedly found nil while unwrapping an Optional value 。 基本上每当我点击其中一个textField时,键盘的这个通知就会被调用, keyboardWillShow的代码将会运行。 我知道, if...let我发言,但我想知道为什么我没有这个。

我不知道我是如何得到这个错误或如何debugging它。 是因为我是从模拟器运行它吗?

以下是打印notification.userInfo给出的内容:

NSRect:{{0,315},{320,253}},AnyHashable(“UIKeyboardIsLocalUserInfoKey”):1,AnyHashable(“UIKeyboardBoundsUserInfoKey”):NSRect:{{0,0} (“UIKeyboardAnimationCurveUserInfoKey”):7,AnyHashable(“UIKeyboardCenterBeginUserInfoKey”):NSPoint:{160,694.5},AnyHashable(“UIKeyboardCenterEndUserInfoKey”):NSPoint:{160,441.5},AnyHashable UIKeyboardFrameBeginUserInfoKey“):NSRect:{{0,568},{320,253}},AnyHashable(”UIKeyboardAnimationDurationUserInfoKey“):0.25])

从文档:

 let UIKeyboardFrameEndUserInfoKey: String 

描述

包含CGRect的NSValue对象的关键字,用于在屏幕坐标中标识键盘的结束帧

你的第二个关键:

 let UIKeyboardAnimationDurationUserInfoKey: String 

描述包含double的NSNumber对象的键,以秒为单位标识animation的持续时间。

所以你需要将第一个投给NSValue,第二个投给NSNumber:

 func keyboardWillShow(_ notification: Notification) { print("keyboardWillShow") guard let userInfo = notification.userInfo else { return } keyboard = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue animaton = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue // your code } 

(如何解决你的问题显然写在狮子座达布斯的答案,所以我会尝试解释我得到的错误之前,我添加!

在Swift 3中, as AnyObject已经成为风险最大的操作之一。 这与称为id-as-Any的最糟糕的新function有关。

在你的代码的这一行中:

  keyboard = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue 

expression式notification.userInfo?[UIKeyboardFrameEndUserInfoKey]的types是Any? 。 正如你看到的,一个可选typesAny? 不应安全地转换为非可选AnyObject 。 但Swift 3转换它创build非可选的_SwiftValue

您可以通过插入以下代码来检查此行为:

 print(type(of: notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject)) 

所以,你试图将非可选的链接.cgRectValue应用于_SwiftValue ,这可能会使Swift 3的特性“隐式types转换_SwiftValue返回Swift值”。

太久了…


不要在Swift 3中使用as AnyObject投射