Swift中 !和 ?的區別及運用。本站提示廣大學習愛好者:(Swift中 !和 ?的區別及運用)文章只能為提供參考,不一定能成為您想要的結果。以下是Swift中 !和 ?的區別及運用正文
置信大家在學習和運用Swift的時分,一定會被 ! 和 ? 搞瘋過, 糾結這兩個符號究竟是個什麼鬼 ?鬼知道什麼時分運用!,什麼時分運用?
上面就說一下! 和 ? 區別以及該怎樣運用!
? 和 ! 究竟是個啥
? 和 ! 其實辨別是Swift言語中對一種可選類型( Optional) 操作的語法糖。 那可選類型是干什麼的呢? Swift中是可以聲明一個沒有初始值的屬性, Swift中引入了可選類型(Optional)來處理這一問題。它的定義是經過在類型生命後加加一個 ? 操作符完成的。
例如: var name: String?
Optional其實是個enum,外面有None和Some兩品種型。其實所謂的nil就是Optional.None , 非nil就是Optional.Some, 然後會經過Some(T)包裝(wrap)原始值,這也是為什麼在運用Optional的時分要拆包(從enum裡取出來原始值)的緣由。
這裡是enum Optional的定義
enum Optional<T> : LogicValue, Reflectable { case None case Some(T) init() init(_ some: T) /// Allow use in a Boolean context. func getLogicValue() -> Bool /// Haskell's fmap, which was mis-named func map<U>(f: (T) -> U) -> U? func getMirror() -> Mirror }
既然這樣, 那關於 var name: String? 該怎樣去了解這句語法呢?
var name: String?
// 下面這個Optional的聲明,是”我聲明了一個Optional類型值,它能夠包括一個String值,也能夠什麼都不包括”,也就是說實踐上我們聲明的是Optional類型,而不是聲明了一個String類型 (這其實了解起來挺蛋疼的...)
? 和 ! 運用
一旦聲明為Optional的,假如不顯式的賦值就會有個默許值nil。判別一個Optional的值能否有值,可以用if來判別:
if name {
// 有值再操作
}
怎樣運用Optional值呢?文檔中也有提到說,在運用Optional值的時分需求在詳細的操作,比方調用辦法、屬性、下標索引等後面需求加上一個?,假如是nil值,也就是Optional.None,會跳當時面的操作不執行,假如有值,就是Optional.Some,能夠就會拆包(unwrap),然後對拆包後的值執行前面的操作,來保證執行這個操作的平安性。
// 例如:
let length = name?.characters.count
PS:關於 Optional 值,不能直接停止操作,否則會報錯。
? 的運用場景:
1.聲明Optional值變量
2.用在對Optional值操作中,用來判別能否能呼應前面的操作
3.運用 as? 向下轉型(Downcast)
下面提到Optional值需求拆包(unwrap)後才干失掉原來值,然後才干對其操作,那怎樣來拆包呢?
拆包有兩種辦法:
可選綁定(Optional Binding)
可選綁定(Optional Binding)是一種更復雜更引薦的辦法來解包一個可選類型。 運用可選綁定來反省可選類型的變量有值還是沒值。假如有值, 解包它並且將值傳遞給一個常量或許變量。
// 例子最為復雜明了 var str: String? = "Hello" let greeting = "World!" if let name = str { let message = greeting + name print(message) } /** 自然言語解釋意思:就是假如str有值,解包它,並且將它的值賦值給name, 然後執行上面的條件語句; 假如str為空, 直接跳過條件語句塊。 */
硬解包
硬解包即直接在可選類型前面加一個感慨號(!)來表示它一定有值。
var str1: String? = "Hello" let greeting = "World!" if (str1 != nil) { let message = greeting + str1! print(message) } /** 下面例子,我們只是自己知道str1一定有值, 所以才直接硬解包了str1變量。 但是萬一有時分我們的覺得是錯的, 那順序在運轉時能夠會呈現嚴重的錯誤. 所以Swift中是引薦先反省可選類型能否有值, 然後再停止解包的! */
錯誤示范:
var str1:String? // str1值能夠是傳過去的值或許從服務器獲取的值 let msg = "Hi" let txt = msg + str1! // runtime error /** 以上代碼在編譯階段不會報錯.由於運用了硬解包, 編譯器以為可選類型是有值的, 所以編譯是經過的. 當代碼運轉起來時, 知名的錯誤將會呈現: `fatal error: Can't unwrap Optional.None` *
PS:關於 ! 操作符,這裡的變量值一定是非nil的!
其實, 還有一種叫隱式拆包(Implicitly Unwrapped Optionals),比方 關於會在viewDidLoad停止初始化的變量,可以直接定義為var str :String! 等於說你每次對這品種型的值操作時,都會自動在操作前補上一個!停止拆包,然後在執行前面的操作,當然假如該值是nil,會報錯crash掉。
舉個很粗淺的栗子:
// 在一個viewController外面,從xib外面拖一個UIImageView控件, 你會發現Xcode會自動給你轉成上面的方式 @IBOutlet weak var headerBGImageView: UIImageView! /** 聲明Implicitly Unwrapped Optionals值,普通用於類中的屬性 */
PS:假如你在隱式解析可選類型沒有值的時分停止取值,會crash。和在沒有值的可選類型外面拆包是一樣的。
! 的運用場景
1.強迫對Optional值停止拆包(unwrap)
2.聲明隱式拆包變量,普通用於類中的屬性
完畢
其實! 和 ? 的問題是很坑的,不要看它僅僅是兩個符號,由於只需有一個不小心,不留意,你會發現項目運轉起來,會莫名的crash掉了,關鍵是Debug形式也不是很方便定位錯誤類型。 自己整理一下關於 可選類型的相關運用,一是記載和穩固所學,而是希望會對大家有所協助。 本文能夠會有錯誤和不妥之處,還望提出,我會及時矯正。