可選類型佣谐、隱式可選類型
在swift中肚吏,可選類型其根源是一個枚舉型,里面有None和Some兩種類型狭魂。其實所謂的nil就是Optional.None, 非nil就是Optional.Some, 然后會通過Some(T)包裝(wrap)原始值罚攀,這里是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 optionalString: String? = "Hello"
optionalString == nil
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}”
大家把optionalName改為nil時看一下會有什么結(jié)果雌澄?按照理解斋泄,應(yīng)該是? = 后的為可選值掷伙,即當(dāng)我們的的變量為nil時是己,這里如果有?=操作任柜,則會使用卒废?=后的值作為默認值沛厨,而不會為nil. 這個等有環(huán)境時,驗證一下摔认。
經(jīng)驗證:
分別執(zhí)行:
var optional :String? = "ok good";//注意?與=號之間有空格?號緊貼最后一個字母不能有空格
println(optional)
輸出為:
ok good
與
var optional :String?//注意?與=號之間有空格?號緊貼最后一個字母不能有空格
println(optional)
輸出為:
nil
來看下官方釋為隱式解包:主要用在一個變量/常量在定義瞬間完成之后值一定會存在的情況逆皮。這主要用在類的初始化過程中。
var optionVariables:String? //?相當(dāng)于下面這種寫法的語法糖
//var optionVariables : Optional<Int>
let value = optionVariables?.hashValue
/*
optionVariables是可選類型的字符串参袱,如果optionVariables是nil电谣,則hashValue也為nil
如果optionVariables不為nil,hashValue就是strValue字符串的哈希值
到這里我們看到了?的兩種使用場景:
1.聲明Optional值變量
2.用在對Optional值操作中抹蚀,用來判斷是否能響應(yīng)后面的操作
*/
//對于可選類型變量剿牺,不能直接進行操作,否則會報錯
//let hashval = optionVariables.hashValue //'String?' does not have a member named 'hashValue'
//因此要訪問值就需要解包环壤,解包有兩種
//第一種:使用if let/var xxx =
if let hv = optionVariables
{
//run ok;
}
//第二種:使用!號
let hv = optionVariables!.hashValue
//這里的!表示“我確定這里的的strValue一定是非nil的晒来,盡情調(diào)用吧” ,比如這種情況:
if optionVariables {
let hashv = optionVariables!.hashValue
}
//{}里的optionVariables一定是非nil的郑现,所以就能直接加上!湃崩,強制拆包(unwrap)并執(zhí)行后面的操作
凡在變量或常量后加上?的都是一個可選變量/可選常量
凡在變量或常量后加上!的都是隱式可選變量/常量,有點難理解接箫,首先該變量或常量滿足可選類型攒读,其主要是可被當(dāng)生一般的變量/常量來使用,而不需要每次都驗證是否有值辛友。
注:如果一個隱式解包的可選類型不包含一個實際值薄扁,那么對它的訪問會拋出一個運行時錯誤。在變量/常量名后面加废累!的情況也是一樣的泌辫。
var possibleString: String? = "An optional string."
//possibleString = nil
println(possibleString) // possibleString 為可選變量,需要使用!來訪問的值
分析:首先 possibleString 因后面帶上了?說明這是一個可選的九默,同時前面加上var為變量,所以這是一個可選類型的變量宾毒。其可選值為 "An optional string." 再來看執(zhí)行println后驼修,可以看出輸出為 An optional string. 這點很明顯。再來看一下把println這句改一下改為 (即在可選變量后面加上一個!號诈铛。)
println(possibleString!) // possibleString 為可選變量乙各,需要使用!來訪問的值
這里結(jié)果與沒有加!號時是完全一樣的,輸出為An optional string.
好幢竹,現(xiàn)在重點來了耳峦,這是很關(guān)鍵的一個測試。把possibleString = nil 這句注釋放開讓其動行焕毫,再分別來看一下println帶!和不帶!的情況:
情況一:不帶蹲坷!號時驶乾,輸出為nil .
var possibleString: String? = "An optional string."
possibleString = nil
println(possibleString)
情況二:再來看一下帶!號
var possibleString: String? = "An optional string."
possibleString = nil
println(possibleString!) // possibleString 為可選變量,需要使用!來訪問的值
這時運行到這句println就會crash了循签。會報
fatal error: Can't unwrap Optional.None
錯誤级乐。
在情況一時,為什么不會報錯县匠,是因為這是一個可選變量當(dāng)變量為nil時风科,自動驗證是否有可選的值,有則使用可選值,在情況二乞旦,加上!訪問符來訪問possibleString 變量贼穆,但由于possibleString設(shè)為了nil (等價于var possibleString: String?) 其并沒有包含一個實際值,所以拋異常.同樣對于下面使用!號來聲明的也一樣
var assumedString: String! = "An implicitly unwrapped optional string."
assumedString = nil
println(assumedString!)
如果你定義了一個可選類型并且沒有給予初始值的時候兰粉,會默認設(shè)置為nil
var surveyAnswer: String? // 初自動設(shè)置為nil
注: Swift 的nil不同于Object-C中的nil. Object-C中故痊,nil是一個指針指向不存在的對象。Swift中亲桦,nil不是指針而是一個特定類型的空值崖蜜。任何類型的可選變量都可以被設(shè)為nil,不光是指針客峭。
在swift中作何變量/常量的聲明都必須帶有初始值豫领,否則就要聲明為可選型。
即var btn:UIButton 這樣是編譯報錯的舔琅。因些必須改為帶初始化的如:
var btn2 :UIButton = UIButton()
或者使用? 和! 來約束等恐。
因此常常聲明可選或隱式可選變量如:
var btn :UIButton? // 默認btn = nil
var edt :UITextField! // 默認edt = nil