2016-09-15 79 views
2

我有這樣的代碼低於當keyboardWillShowNotification被稱爲運行:unexpectedly found nil while unwrapping an Optional value意外地發現零而展開的可選值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 
    }) 
} 

我在第二行說得到一個錯誤。基本上每當我點擊其中一個textField時,這個鍵盤通知就會被調用,並且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

登錄'notification.userInfo'不要使用as AnyObject鑄造。查看實際存在的密鑰。 – rmaddy

+0

噢,讓我試試。 – CapturedTree

+0

我在問題中添加了什麼打印出來。它顯示'UIKeyboardFrameEndUserInfoKey'可用。 – CapturedTree

回答

3

從文檔:

let UIKeyboardFrameEndUserInfoKey: String 

說明

標識所述鍵盤在屏幕的 結束幀用於容納的CGRect一個NSValue對象的關鍵座標

你的第二關鍵字:

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值「。

獲取太長......


斯威夫特3

+0

你好,很抱歉遲到的答覆,謝謝你的詳細解答!我有一個問題:你在這裏陳述道:「正如你看到的,一個可選類型'Any?'不應該安全地轉換爲非可選'AnyObject',但Swift 3通過創建非可選'_SwiftValue'來轉換它」不理解這部分:swift 3將它轉換爲非可選的'_SwiftValue'。你的意思是說''notification.userInfo?[UIKeyboardFrameEndUserInfoKey]'是'Any?'的值是否被轉換爲非可選類型'_SwiftValue'?此外'_SwiftValue'指的是什麼? – CapturedTree

+1

@ 1290,_你的意思是說,任何?'notification.userInfo?[UIKeyboardFrameEndUserInfoKey]的值被轉換爲非可選類型'_SwiftValue'?絕對是的。 _SwiftValue在這裏指的是什麼_這是一個隱藏類型,目前還沒有透露 - 它是一個引用類型。 - 它可以包含任何Swift的值。 - Swift運行時知道如何檢索包含在其中的原始值,並且可能會自動將其轉換爲Swift類型。 – OOPer

+0

哦,我現在看到了!非常感謝你的明確解釋幫助了很多。 – CapturedTree

相關問題