
在 Swift 中我們會接觸到可選類型 Optional,剛開始寫代碼時會被變量后的 ?、!、?? 等符號弄得稀里糊涂。
首先,對于以下代碼:
var num: Int?
num = 10
if num is Optional<Int> {
print("它是可選類型")
} else {
print("它是Int類型")
}
在IDE中的if上一定會出現(xiàn)這樣一個warning:'is' test is always true。也就是說 num 不是 Int 類型,而是 Optional 類型。
1. Optional類型
可選類型聲明,如下:
var num : Int?
// let num2 : Int? // let類型變量只可被初始化一次
以上聲明的意思是:聲明了一個變量,它的值可能是一個 Int 值,也可能為 nil 。也即,實際上聲明的是 Optional 類型的變量,而不是聲明了一個 Int 類型的。
正是因為 num 是一個可選類型,所以它才能賦值為 nil ,var num : Int = nil,這樣是不可能賦值成功的,因為Int類型中沒有 nil 這個概念!在 OC 中對象都可以賦值為 nil ,但在 Swift 中能賦值為 nil 的只有 Optional 類型!
2. 關(guān)于解包
解包符號為 !
如果確定一個可選類型的值一定存在,那么我們使用 !進行解包來獲取它的值,或者使用 Optional Binding 來處理。
let possiablestring: String? = "An possiable string"
print(possiablestring!) // 強制解包 確定possiablestring的值確實存在,不需要每次都驗證它的值 let strValues = possiablestring!.hashValue
也可以把 隱式解包可選類型 當成對每次使用的時候自動解包的可選類型。隱式解包不是每次使用的時候 在變量/常量后面加 !,而是直接在定義的時候加 !。
let assumString: String! = "an optional string"
print(assumString, assumString.hashValue)
! 的使用場景:
- 強制對 可選選類變量 進行解包;
- 聲明 隱式解包的可選類型變量 的時候, 一般用于類中的屬性。
3. 解包的基本思路
使用 if let 或者 guard let,而非強制解包。對于如下方法:
func getHeight(_ height: Float?) -> Float? {
if height != nil {
return height! / 100
}
return nil
}
以上代碼中使用 ! 對height進行強制解包,然后參與運算,其中每使用一次都要進行強制解包。強制解包過程中一旦解包失敗,就會引起崩潰,安全的解包行為應(yīng)該是通過if let 或者guard let,這種被稱為可選綁定的操作來處理的:
// if let
func getHeight(_ height: Float?) -> Float? {
if let unwrapedHeight = height {
return unwrapedHeight / 100
}
return nil
}
//// guard let
//func getHeight(_ height: Float?) -> Float? {
// guard let unwrapedHeight = height else {
// return nil
// }
// return unwrapedHeight / 100
//}
注意:
對于 if let ,大括號中是符合條件的正常情況,而外部是非正常情況;
對于 guard let ,guard let else中的大括號是異常情況,而外部返回的是正常情況。
多幾個前置 guard let 進行判斷,有時可以讓代碼更具可讀性。
4. 可選鏈的解包
對于以下兩個類:
class Person {
var phone: Phone?
}
class Phone {
var number: String?
}
解包時不必一層層進行判斷,因為可選鏈中一旦有某個鏈為 nil ,那么就會返回 nil ,過程如下:
let dora = Person()
guard let number = dora.phone?.number else {
return
}
5. _Nonnull、nonnull 與 可選類型 的關(guān)系
對于拼接字符串方法,OC 中是這樣:
- (NSString *)stringByAppendingString:(NSString *)aString;
Swift 中是這樣:
public mutating func append(_ other: String)
僅從 API 來看,OC 的入?yún)⑹呛芪kU的,因為類型是 NSString * ,那么 nil 也可以傳入,這樣會崩掉,應(yīng)該寫成:
- (NSString *)stringByAppendingString:(NSString * _Nonnull)aString;
//// 或
//- (NSString *)stringByAppendingString:(nonnull NSString *)aString;
這樣以便提示程序員,入?yún)⒉荒転榭?。Swift 則不會出現(xiàn)這種情況,other 后面的類型為String ,而不是 String? ,說明入?yún)⑹且粋€非可選類型。
參考文章:
http://www.mamicode.com/info-detail-1160599.html
http://www.itdecent.cn/p/4bfbb0ba4d32