Swift--可選(新特性)

可選 
使用可選(optionals)來處理值可能缺失的情況。可選表示:有值,等於  x 或者 沒有值 

注意:C 和  Objective-C 中並沒有可選這個概念。最接近的是  Objective-C 中的一個特性,一個方法要不返回一個對象要不返回 nil,nil 表示“缺少一個合法的對象”。然而,這隻對對象起作用——對於結構體,基本的  C 類型或者枚舉類型不起作用。對於這些類型,Objective-C 方法一般會返回一個特殊值(比如 NSNotFound)來暗示值缺失。這種方法假設方法的調用者知道並記得對特殊值進行判斷。然而,Swift  的可選可以讓你暗示任意類型的值缺失,並不需要一個特殊值。 
來看一個例子。Swift  的 String 類型有一個叫做 toInt 的方法,作用是將一個 String 值轉換成一個 Int 值。然而,並不是所有的字符串都可以轉換成一個整數。字符串"123"可以被轉換成數字 123,但是字符串"hello, world"不行。 
  
下面的例子使用 toInt 方法來嘗試將一個 String 轉換成 Int: 
1.  let possibleNumber = "123"  
2.  let convertedNumber = possibleNumber.toInt()  
3.  // convertedNumber 被推測爲類型 "Int?", 或者類型 "optional Int"  

因爲 toInt 方法可能會失敗,所以它返回一個可選的(optional)Int,而不是一個 Int。一個可選的 Int 被寫作 Int?而不是 Int。問號暗示包含的值是可選,也就是說可能包含 Int 值也可能不包含值。(不能包含其他任何值比如 Bool 值或者 String 值。只能是 Int 或者什麼都沒有。)

 

if  語句以及強制解析 
你可以使用 if 語句來判斷一個可選是否包含值。如果可選有值,結果是 true;如果沒有值,結果是 false。 
  
當你確定可選包確實含值之後,你可以在可選的名字後面加一個感嘆號(!)來獲取值。這個驚歎號表示“我知道這個可選有值,請使用它。”這被稱爲可選值的強制解析(forced unwrapping): 
1.  if convertedNumber {  
2.      println("\(possibleNumber) has an integer value of \(convertedNumb
er!)")  
3.  } else {  
4.      println("\(possibleNumber) could not be converted to an integer")  
5.  }  
6.  // 輸出 "123 has an integer value of 123"  

注意:使用!來獲取一個不存在的可選值會導致運行時錯誤。使用!來強制解析值之前,一定要確定可選包含一個非 nil 的值。

 

可選綁定 
使用可選綁定(optional binding)來判斷可選是否包含值,如果包含就把值賦給一個臨時常量或者變量。可選綁定可以用在 if 和 while 語句中來對可選的值進行判斷並把值賦給一個常量或者變量。if 和 while 語句,請參考控制流。 
  
像下面這樣在 if 語句中寫一個可選綁定: 
1.  if let constantName = someOptional {  
2.      statements  
3.  }  
你可以像上面這樣使用可選綁定來重寫 possibleNumber 這個例子: 
1.  if let actualNumber = possibleNumber.toInt() {  
2.      println("\(possibleNumber) has an integer value of \(actualNumber)
")  
3.  } else {  
4.      println("\(possibleNumber) could not be converted to an integer")  
5.  }  
6.  // 輸出 "123 has an integer value of 123"  
這段代碼可以被理解爲:  
“如果 possibleNumber.toInt 返回的可選 Int 包含一個值,創建一個叫做 actualNumber 的新常量並將可選包含的值賦給它。” 如果轉換成功,actualNumber 常量可以在 if 語句的第一個分支中使用。它已經被可選包含的值初始化過,所以不需要再使用!後綴來獲取它的值。在這個例子中,actualNumber 只被用來輸出轉換結果。 
  

你可以在可選綁定中使用常量和變量。如果你想在 if 語句的第一個分支中操作actualNumber 的值,你可以改成 if var actualNumber,這樣可選包含的值就會被賦給一個變量而非常量。 


nil 
你可以給可選變量賦值爲 nil 來表示它沒有值: 
1.  var serverResponseCode: Int? = 404  
2.  // serverResponseCode  包含一個可選的 Int 值 404  
3.  serverResponseCode = nil  
4.  // serverResponseCode  現在不包含值  
注意:nil 不能用於非可選的常量和變量。如果你的代碼中有常量或者變量需要處理值缺失的情況,請把它們聲明成對應的可選類型。 
如果你聲明一個可選常量或者變量但是沒有賦值,它們會自動被設置爲 nil: 
1.  var surveyAnswer: String?  

2.  // surveyAnswer 被自動設置爲 nil  


注意:Swift  的 nil 和 Objective-C 中的 nil 並不一樣。在 Objective-C 中,nil 是一個指向不存在對象的指針。在  Swift  中,nil 不是指針——它是一個確定的值,用來表示值缺失。任何類型的可選都可以被設置爲 nil,不只是對象類型。 


隱式解析可選 

如上所述,可選暗示了常量或者變量可以“沒有值”。可選可以通過 if 語句來判斷是否有值,如果有值的話可以通過可選綁定來解析值。 
  
有時候在程序架構中,第一次被賦值之後,可以確定一個可選總會有值。在這種情況下,每次都要判斷和解析可選值是非常低效的,因爲可以確定它總會有值。 這種類型的可選被定義爲隱式解析可選(implicitly unwrapped optionals)。把想要用作可選的類型的後面的問號(String?)改成感嘆號(String!)來聲明一個隱式解析可選。 
  
當可選被第一次賦值之後就可以確定之後一直有值的時候,隱式解析可選非常有用。隱式解析可選主要被用在  Swift  中類的構造過程中,請參考類實例之間的循環強引用。 
  
一個隱式解析可選其實就是一個普通的可選,但是可以被當做非可選來使用,並不需要每次都使用解析來獲取可選值。下面的例子展示了可選 String 和隱式解析可選 String 之間的區別: 
1.  let possibleString: String? = "An optional string."  
2.  println(possibleString!)  // 需要驚歎號來獲取值  
3.  // 輸出 "An optional string."   
4.    
5.  let assumedString: String! = "An implicitly unwrapped optional string.
"  
6.  println(assumedString)   // 不需要感嘆號  
7.  // 輸出 "An implicitly  unwrapped optional  string."  
你可以把隱式解析可選當做一個可以自動解析的可選。你要做的只是聲明的時候把感嘆號放到類型的結尾,而不是每次取值的可選名字的結尾。 
  
注意:如果你在隱式解析可選沒有值的時候嘗試取值,會觸發運行時錯誤。和你在沒有值的普通可選後面加一個驚歎號一樣。 
你仍然可以把隱式解析可選當做普通可選來判斷它是否包含值: 
1.  if assumedString {  
2.      println(assumedString)  
3.  }  
4.  // 輸出 "An implicitly  unwrapped optional  string."  
你也可以在可選綁定中使用隱式解析可選來檢查並解析它的值: 
1.  if let definiteString = assumedString {  
2.      println(definiteString)  
3.  }  
4.  // 輸出 "An implicitly  unwrapped optional  string."  
注意:如果一個變量之後可能變成 nil 的話請不要使用隱式解析可選。如果你需要在變量的生命週期中判斷是否是 nil 的話,請使用普通可選類型。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章