在展开可选值时意外发现nil keyboardWillShow

时间:2016-09-15 20:28:46

标签: ios swift swift3 uikeyboard nsnotification

我有下面的代码,当调用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。基本上每当我点击其中一个textFields时,都会调用键盘的这个通知,并且keyboardWillShow中的代码将会运行。我知道我放了if...let个陈述,但我想知道为什么我这样做了。

我不确定我是如何得到此错误或如何调试它。是因为我是从模拟器运行的吗?

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

  

可选([AnyHashable(" UIKeyboardFrameEndUserInfoKey"):NSRect:{{0,315},{320,253}},AnyHashable(" UIKeyboardIsLocalUserInfoKey"):1,AnyHashable( " UIKeyboardBoundsUserInfoKey"):NSRect:{{0,0},{320,253}},AnyHashable(" 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])

2 个答案:

答案 0 :(得分:3)

来自文档:

let UIKeyboardFrameEndUserInfoKey: String 
  

描述

     

包含标识CGRect的CGRect的NSValue对象的键   屏幕坐标中键盘的结束帧

你的第二把钥匙:

let UIKeyboardAnimationDurationUserInfoKey: String
  

描述包含double的NSNumber对象的键   以秒为单位识别动画的持续时间。

所以你需要将第一个转换为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
}

答案 1 :(得分:2)

(如何解决你的问题清楚写在Leo Dabus的答案中,所以我会尝试解释我在添加!之前得到的错误。)

在Swift 3中,as AnyObject已经成为最危险的操作之一。 它与称为id-as-Any的最差新功能有关。

在你的代码的这一行:

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

表达式notification.userInfo?[UIKeyboardFrameEndUserInfoKey]的类型为Any?。如您所见,不应将可选类型Any?安全地转换为非可选AnyObject。但Swift 3通过创建非可选_SwiftValue来转换它。

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

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

所以,你试图将非可选链接.cgRectValue应用于_SwiftValue,这可能会混淆Swift 3的功能:“隐式类型转换_SwiftValue回到Swift值”

太长了......

请勿在Swift 3中使用as AnyObject投射