2016-09-15 1 views
2

У меня есть этот код, приведенный ниже, который работает, когда keyboardWillShowNotification называется:неожиданно нашли ноль в то время как разворачивание необязательное значение keyboardWillShow

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. В принципе, всякий раз, когда я нажимаю на один из текстовых полей, это уведомление для клавиатуры будет вызвано, и код в 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])

+0

Log 'notification.userInfo'. Посмотрите, какие клавиши существуют на самом деле. – rmaddy

+0

О да, дайте мне попробовать. – CapturedTree

+0

Я добавил в свой вопрос, что распечатывается. Это показывает, что доступен 'UIKeyboardFrameEndUserInfoKey'. – CapturedTree

ответ

3

Из документов:

let UIKeyboardFrameEndUserInfoKey: String 

Описание

Ключ для объекта NSValue, содержащего CGRect, который идентифицирует конечный кадр клавиатуры в координатах экрана

Ваш второй :

let UIKeyboardAnimationDurationUserInfoKey: String 

Описание Ключ для объекта 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 
} 
+0

Здравствуйте! Какова цель хранения значения ключа 'UIKeyboardFrameEndUserInfoKey' в' NSValue'? Почему бы просто не сохранить его в 'CGRect'? Я читал онлайн, что «NSValue» представляет собой простой контейнер для одного элемента данных C или Objective-C. Таким образом, 'CGRect' является объектом данных Objective-C, поэтому мы будем обертывать это в' NSValue'? – CapturedTree

2

(Как исправить ваш вопрос ясно написано в ответ Лео 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, что может привести к путанице Свифта 3 в функции: «неявное преобразование типов _SwiftValue вернуться к значению Swift ".

Получение слишком долго ...


НЕ используйте as AnyObject отливку в Swift 3

+0

Привет, очень жаль позднего ответа и спасибо за подробный ответ! У меня есть один вопрос: вы заявили здесь: «Как вы видите, необязательный тип« Any? »Не должен быть безопасно преобразован в необязательный« AnyObject ». Но Swift 3 преобразует его с созданием необязательного' _SwiftValue' ' Не понимаю эту часть: этот быстрый 3 преобразует его в необязательный '_SwiftValue'. Вы имеете в виду, что значение 'notification.userInfo? [UIKeyboardFrameEndUserInfoKey]', которое является 'Any? ', Преобразуется в необязательный тип' _SwiftValue'? И что здесь говорит '_SwiftValue'? – CapturedTree

+1

@ 1290, _Вы имеете в виду, что значение notification.userInfo? [UIKeyboardFrameEndUserInfoKey], которое является 'Any? ', Преобразуется в необязательный тип' _SwiftValue'? _ Абсолютно да. _What это '_SwiftValue' ссылается здесь? _ Это скрытый тип и пока еще не раскрывается, - это ссылочный тип. - Он может содержать любое значение Swift. - Быстрая среда выполнения знает, как получить исходное значение, содержащееся в нем, и в случаях может автоматически преобразовывать его в типы Swift. – OOPer

+0

О, я вижу сейчас! Большое вам спасибо за то, что ясное объяснение помогло многим. – CapturedTree

Смежные вопросы

 Смежные вопросы