介紹
可選鏈,英文叫Optional Chaining,是表示變量、屬性等值可為空,也就是值可能為nil。若有值,則可成功獲取值;若無(wú)值,則返回nil。多個(gè)連續(xù)的調(diào)用可以被鏈接在一起形成一個(gè)調(diào)用鏈,如果其中任何一個(gè)節(jié)點(diǎn)為空(nil)將導(dǎo)致整個(gè)鏈調(diào)用失敗。
在開發(fā)中會(huì)大量地使用可選類型屬性、變量等,因?yàn)樵谡Z(yǔ)義上表示值可能有也可能沒有。善于使用Optional,可簡(jiǎn)化開發(fā)。
注意:Swift的可選鏈調(diào)用和ObjectiveC中的消息為空有點(diǎn)像,但是Swift可以使用在任意類型中,并且能夠檢查調(diào)用是否成功。
Optional枚舉
下面是Optional檢舉類型的聲明:
public enum Optional : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
/// Construct a `nil` instance.
public init()
/// Construct a non-`nil` instance that stores `some`.
public init(_ some: Wrapped)
/// If `self == nil`, returns `nil`.? Otherwise, returns `f(self!)`.
@warn_unused_result
public func map(@noescape f: (Wrapped) throws -> U) rethrows -> U?
/// Returns `nil` if `self` is nil, `f(self!)` otherwise.
@warn_unused_result
public func flatMap(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
/// Create an instance initialized with `nil`.
public init(nilLiteral: ())
}
其中無(wú)值用表示None表示,而有值用Some表示有值。
var count: Optional
這么聲明與下面的聲明是一樣的:
var count: Int?
如何聲明Optional
聲明為可選,可以使用?或者!,如果使用?,其值為空時(shí),調(diào)用也沒有關(guān)系,只是什么也沒有做而已。但是,如果使用!聲明,如果其值為空,我們調(diào)用就會(huì)造成crash。對(duì)于!表示選擇編譯器,其一定有值。
var optionalValue: String?
// Optional("nonnull")
print(optionalValue)
var name: String!
// Crash原因:取值是,發(fā)現(xiàn)是nil,而聲明是就告訴過(guò)編譯器,不可能為空
// fatal error: unexpectedly found nil while unwrapping an Optional value
print(name)
使用!強(qiáng)制UnWrapper
如果我們?cè)谑褂弥校枰猽nwrapper呢?如果我們直接使用?來(lái)獲取,也可以直接使用!強(qiáng)制獲取。
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
我們聲明一個(gè)Person對(duì)象:
let john = Person()
let residence = Residence()
biaoge.residence = residence
獲取numberOfRooms的值時(shí),我們可以直接使用!取,這樣取出來(lái)的值就不是可選的。像下面這樣,那么roomCount的類型為Int:
let roomCount = john.residence!.numberOfRooms
當(dāng)然我們也可以使用?獲取,則這樣獲取的話,roomCount的類型就是Int?
let roomCount = john.residence?.numberOfRooms
對(duì)于可選類型,我們通常使用下面的方式:
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
這種方式是非常常用的,在開發(fā)中也會(huì)到處看到類似這樣的代碼。嘗試去獲取值,如果成功地取得值,就會(huì)是true,否則就會(huì)是false。
可選賦值
對(duì)于上面的john.residence?.numberOfRooms,我們可以設(shè)置其值:
john.residence?.numberOfRooms = 10
由于residence是可選類型,我們?cè)谑褂脮r(shí),添加上?,就算residence是空的,這么設(shè)置也不會(huì)有問(wèn)題。當(dāng)然我們也可以使用!來(lái)告訴編譯器,residence一定不會(huì)為空,但是一旦其值為空就會(huì)Crash。所以,無(wú)論何時(shí),我們直接使用?就好了,不用使用!。
如果有很多個(gè)可空類型,一樣都使用?就好了。類似下面這樣:
// 只是假設(shè)
let testId = john?.residence?.test?.id
訪問(wèn)下標(biāo)
這里我們?cè)O(shè)計(jì)一個(gè)可空數(shù)組,然后通過(guò)訪問(wèn)下標(biāo)的方式獲取值。由于array是可空數(shù)組,不能直接訪問(wèn),因此需要通過(guò)?或者!訪問(wèn)。
let array: [Int]? = [1, 2]
// 如果這里直接使用array[0]來(lái)抱錯(cuò)的
let first = array?[0]
當(dāng)然我們也可以直接使用!的方式來(lái)訪問(wèn),因?yàn)檫@里我們確定array[0]一定不會(huì)越界。下面這么寫也是正確的。
let fiset = array![0]
可選參數(shù)和返回值
在設(shè)計(jì)函數(shù)的時(shí)候,我們經(jīng)常是不確定其一定有值的,因此我們會(huì)返回可空類型。
func funcName(name: String?) ->String? {
return nil
}
學(xué)習(xí)路線
關(guān)于學(xué)習(xí)Swift的路徑說(shuō)明,請(qǐng)閱讀文章:http://mp.weixin.qq.com/s?__biz=MzIzMzA4NjA5Mw==&mid=400386772&idx=1&sn=15328f06c1d3dd3a964d24cf1aad5c4d#wechat_redirect