Swift可選值(Optional Values)以及?和!使用

Optional(可選類型)

Optional是Swift中引入的新類型. 表示可以有值也可以沒值. 當(dāng)它沒值時, 就是nil. Optional類型其實是枚舉:

enum Optional<T> : Reflectable, NilLiteralConvertible {
    case None
    case Some(T)
    init()
    init(_ some: T)

    /// Haskell's fmap, which was mis-named
    func map<U>(f: (T) -> U) -> U?
    func getMirror() -> MirrorType
    static func convertFromNilLiteral() -> T?
}

當(dāng)Optional沒有值時,返回的nil其實就是Optional.None,即沒有值。除了None以外,還有一個Some,當(dāng)有值時就是被Some<T>包裝的真正的值,所以我們拆包的動作其實就是將Some里面的值取出來。

Swift和OC中nil的區(qū)別
  1. OC中,nil是一個指向不存在對象的指針;
  2. Swift中,nil不是指針,它是一個確定的值,用于表示值缺失。任何類型的可選狀態(tài)都可以設(shè)置為nil,不只是對象類型(當(dāng)基礎(chǔ)類型(整形、浮點、布爾等)沒有值時,也是nil);
定義

定義一個Optional的值只需要在類型后面加上問號(?),如:

var str: String?

另外:在上面可以看到,Optional其實就是一個枚舉,然后給它指定一個類型就行了,所以下面這兩種方法都能聲明一個Optional值:

var str: String! = "Hello World!"
var str2: Optional<String>

一個Optional值和非Optional值的區(qū)別就在于:Optional值未經(jīng)初始化雖然為nil,但普通變量連nil都沒有:

//未被初始化,但是是一個Optional類型,為nil
var str: String?
str //輸出nil
//未被初始化,也不是Optional類型
var str2: String
str2    //使用時出錯
使用

關(guān)于! 和 ? 使用場景

?的使用場景
1)聲明Optional值變量
2)在對Optional值操作中,用來判斷是否能響應(yīng)后面的操作

!的使用場景
1)強制對Optional值進(jìn)行拆包
2)聲明隱式拆包變量,一般用于類中的屬性

**對于可選類型, 使用之前需要拆包才不會報錯. 拆包有兩種方式. **

顯式拆包

  1. Optional Binding

正常情況下,let pet = jackon.pet 的返回值不是 Bool,而是“有值”或者“沒有值”,不能直接用于條件表達(dá)式。但是 if let 的搭配是一種僅僅針對 Optional 類型的特殊的情況,蘋果有意在編譯器做了這種處理。

if let str = strValue {
   let hashValue = str.hashValue
}
  1. 通過! str!
    對比拆包前后,對str的輸出:

    var str: String? = "Hello World!"
    str //{Some "Hello World!"}
    str! //Hello World!

隱式拆包

通過在聲明時的數(shù)據(jù)類型后面加一個感嘆號(!)來實現(xiàn):

var str: String! = "Hello World!"
str //Hello World!

可以看到?jīng)]有使用(?)進(jìn)行顯式的折包也得到了Some中的值,這個語法相當(dāng)于告訴編譯器:在我們使用Optional值前,這個Optional值就會被初始化,并且總是會有值,所以當(dāng)我們使用時,編譯器就幫我做了一次拆包。如果你確信你的變量能保證被正確初始化,那就可以這么做,否則還是不要嘗試為好。

Optional Chaining

當(dāng)一個Optional值調(diào)用它的另一個Optional值的時候,Optional Chaining就形成了,基本上,Optional Chaining就是總是返回一個Optional的值,只要這個Chaining中有一個值為nil,整條Chaining就為nil,和Objective-C的向nil發(fā)消息類似。

//不使用Optional Chaining需要判斷兩次
if let pet = jackon.pet {
    if let toy = pet.favoriteToy {
        toy.name
    }
}
//使用Optional Chaining只需要判斷一次
if let toy = jackon.pet?.favoriteToy {
    toy.name
}

Optional Chaining除了能將屬性返回的類型變?yōu)?code>Optional外,連方法的返回值都能強制變?yōu)?code>Optional,哪怕這個方法沒有返回值,但是別忘了,Void也算是一個類型:

typealias Void = ()

如果Pet類有一個玩玩具的play方法的話,就可以這樣來判斷是否會調(diào)用成功:

if let p: Void = jackon.pet?.play() {
    "play is called"
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容