Swift中?和!使用總結
Optional(可選型別)
Swift的可選(Optional)型別,用於處理值缺失的情況。可選表示“那兒有一個值,並且它等於x”或者“那兒沒有值,為nil”。它的定義通過在型別聲明後加一個 ?
操作符來完成的 :
var str = String?
Optional
其實是個 enum
,裡面有 None
和 Some
兩種型別。其實所謂的 nil
就是 Optional.None
,當你宣告一個可選變數的時候沒有提供初始值,它的值預設為 nil
。 非nil
就是 Optional.Sonme
,然後會通過 Some(T)
包裝(wrap
)原始值,這也是為什麼在使用 Optional
unwrap
: 從 enum
中取出來原始值)的原因x。下面是 enum Optional
的定義 :
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
public init(_ some: Wrapped)
public func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?
public func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
public init(nilLiteral: ())
public var unsafelyUnwrapped: Wrapped { get }
}
既然這樣, 那我們如何理解上述變數的宣告呢?
var str = String?
//我聲明瞭一個Optional型別的變數,它可能包含一個String值,也可能什麼都不包含,即nil
也就是說我們實際上宣告的是一個 Optional
型別,而不是 String
型別。
? 和 ! 的比較
舉例 :
import Cocoa
var str : String?
str = "Hello World"
if str != nil {
//print(str)
print(str!)
}
else {
print("字串為nil")
}
輸出結果為: Hello World
怎麼使用 Optional
值呢?在蘋果文件中也有提到說,在使用 Optional
值的時候需要在具體的操作,比如呼叫方法、屬性、下標索引等前面需要加上一個?,如果是 nil
值,也就是 Optional.None
,會跳過後面的操作不執行,如果有值,就是 Optional.Some
,可能就會拆包(unwrap
),然後對拆包後的值執行後面的操作,來保證執行這個操作的安全性。
舉例如下:
let length = str?.count
//如果你確定有值得話,也可以這樣寫
//let length = str!.count
注意
- 如果是執行
print(str)
這句話,那麼輸出為Optional("Hello World")
。 - 使用
!
來獲取一個不存在的可選值會導致執行時錯誤。使用!
來強制解析值之前,一定要確定可選包含一個非nil
的值。
拆包(unwrap)
上文提到 Optional
值需要拆包才能得到原來值,並判斷其值是否為空才能對其操作。下面介紹兩種拆包方法:
1.可選繫結(optional binding)
使用可選繫結(optional binding)來判斷可選型別是否包含值,如果包含就把值賦給一個臨時常量或者變數。可選繫結可以用在if和while語句中來對可選型別的值進行判斷並把值賦給一個常量或者變數。
舉例如下:
import Cocoa
var str : String? = "Hello"
let world = "World"
if let const = str{
print(const + " " + world)
}
else {
print("str is nil")
}
2.硬解包
即直接在可選型別後面加一個 !
來表示它肯定有值。
舉例如下:
import Cocoa
var str : String? = "Hello"
let world = "World"
if str != nil{
print(str! + " " + world)
}
else {
print("str is nil")
}
錯誤示範
import Cocoa
var str:String?
let world = "Hi"
print(str! + world)
以上程式碼在編譯階段不會報錯.因為使用了硬解包, 編譯器認為可選型別是有值的, 所以編譯是通過的。當代碼執行起來時,會報錯:
Fatal error: Unexpectedly found nil while unwrapping an Optional value.
隱式拆包(自動解析)
你可以在宣告可選變數時使用感嘆號 !
替換問號?
。這樣可選變數在使用時就不需要再加一個感嘆號 !
來獲取值,它會自動解析。
舉例如下 :
import Cocoa
var str:String!
str = "Hello World!"
if str != nil {
print(str)
}else{
print("str is nil")
}
等於說你每次對這種型別的值操作時,都會自動在操作前補上一個 !
進行拆包,然後在執行後面的操作,當然如果該值是 nil
,會報錯crash掉。
總而言之,?
和 !
坑還是很多的,需要不斷在實踐中檢驗和體會。
參考自 :
- https://www.jianshu.com/p/89a2afb82488
- http://www.runoob.com/swift/swift-optionals.html