问题
I have this code below which runs when the keyboardWillShowNotification is called:
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
})
}
I am getting an error on the second line saying: unexpectedly found nil while unwrapping an Optional value
. Basically whenever I click on one of the textFields this notification for the keyboard will be called and the code in keyboardWillShow
will run. I know I put if...let
statements but I want to know why I am getting nil for this.
I am not sure how I am getting this error or how to debug it either. Is it because I am running it from the simulator?
Here is what printing the notification.userInfo gives:
Optional([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])
回答1:
From the docs:
let UIKeyboardFrameEndUserInfoKey: String
Description
The key for an NSValue object containing a CGRect that identifies the end frame of the keyboard in screen coordinates
Your second key:
let UIKeyboardAnimationDurationUserInfoKey: String
Description The key for an NSNumber object containing a double that identifies the duration of the animation in seconds.
So you need to cast the first one to NSValue and the second one to 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
}
回答2:
(How to fix your issue is clearly written in Leo Dabus's answer, so I will try to explain the error I was getting before I added the ! .)
In Swift 3, as AnyObject
has become one of the most risky operation.
It's related to the worst new feature called as id-as-Any.
In this line of your code:
keyboard = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue
The type of expression notification.userInfo?[UIKeyboardFrameEndUserInfoKey]
is Any?
. As you see, an Optional type Any?
should not be safely converted to non-Optional AnyObject
. But Swift 3 converts it with creating non-Optional _SwiftValue
.
You can check this behaviour with inserting this code:
print(type(of: notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject))
So, you are trying to apply non-optional-chaining .cgRectValue
to _SwiftValue
, which may be confusing the Swift 3's feature: "implicit type conversion _SwiftValue
back to the Swift value".
Getting too long...
Do NOT use as AnyObject
casting in Swift 3
来源:https://stackoverflow.com/questions/39519822/unexpectedly-found-nil-while-unwrapping-an-optional-value-keyboardwillshow