程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> Swift中 !和 ?的區別及運用

Swift中 !和 ?的區別及運用

編輯:更多關於編程

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形式也不是很方便定位錯誤類型。 自己整理一下關於 可選類型的相關運用,一是記載和穩固所學,而是希望會對大家有所協助。 本文能夠會有錯誤和不妥之處,還望提出,我會及時矯正。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved