- 可選項,也叫做可選類型蕊温。定義為可選類型后,可以設(shè)置為
nil
- 在類型名后面加個問號
?
來定義可選類型 - 可選類型如果不初始化蝌麸,則默認為
nil
var name : String? /*等同于*/ var name : String? = nil
1. 強制解包
- 可選項是對其它類型的一種包裝拔第,可以將它理解為一個盒子
- 如果為
nil
咕村,那么它就是一個空盒子 - 如果不為
nil
,那么盒子里包裝的是:被包裝類型的數(shù)據(jù)
var name : String? = nil
let arr = ["jack","uzi","godV","rookie"]
func getObj(index:Int) -> String?{
if index<0 || index >= arr.count {
return nil
}else{
return arr[index]
}
}
print(name)
print(getObj(index: 3))
/*
nil
Optional("rookie")
*/
- 如果要從可選項中取出被包裝的數(shù)據(jù)蚊俺,則需要使用感嘆號 !進行強制解包
-
如果對值為
nil
的可選項進行強制解包懈涛,將會產(chǎn)生運行時錯誤
錯誤信息:Fatal error: Unexpectedly found nil while unwrapping an Optional value
2. 可選綁定
- 可以使用
可選項綁定
來判斷可選項是否包含值 - 如果包含就自動解包,把值賦給一個臨時的常量 或者 變量泳猬,并返回true批钠,否則返回 false
let num = Int("123")
print(num)//Optional(123)
if let num = Int("123"){
print("num:",num)//num: 123
}else{
print("字符串轉(zhuǎn)換失敗")
}
3. if 中的可選綁定
可選項在進行 與(&&) 運算時。不能直接使用 &&得封,可以用逗號分隔的方式
如下:
if let a = Int("12") {
if let b = Int("44") {
if a < b && b < 100 {
print("\(a) < \(b) < 100")
}
}
}
//等同于
if let a = Int("12"),
let b = Int("44"),
a < b && b < 100{
print("\(a) < \(b) < 100")
}
3. while 中的可選綁定
//遍歷數(shù)組埋心,進行累加,如果遇到非數(shù)字忙上,停止遍歷
var strs = ["1","2","-3","3","4","5",]
var index:Int = 0
var sum:Int = 0
while
index < strs.count,
let obj = Int(strs[index]){
sum += obj
index += 1
}
print("sum:",sum)//12
4 ?? 空合并運算符
示例:a ?? b
a:必須是可選項
b:可選項 或者 不是可選項
b跟a的存儲類型必須相同
- 如果 a 不為 nil踩窖,則返回 a
- 如果 a 為 nil, 則返回b
- 如果b不是可選項晨横,返回 a 時洋腮,則a會自動解包
let a: Int? = 1
let b: Int? = 2
let c: Int = 3
let d: Int? = nil
print(a ?? b, a ?? c, d ?? b) //Optional(1) 1 Optional(2)
4.1 ?? 跟if let 配合使用
- 類似于 if v1 != nil || v2 != nil
let v1:Int? = nil
let v2:Int? = 2
if let c = v1 ?? v2{
print(c)
}
//類似于 if v1 != nil || v2 != nil
- 類似于 if v1 != nil && v2 != nil
let v1:Int? = nil
let v2:Int? = 2
if let c = v1,
let d = v2{
print("result_c:",c)
print("result_d:",d)
}
5. guard 語句
guard 條件 else{
//退出當(dāng)前作用域
}
- 當(dāng)
guard
語句的條件為false
時, 就會執(zhí)行大括號里的代碼 - 當(dāng)
guard
語句的條件為true
時手形,就會調(diào)過guard
-
guard
語句特別適合用來"提前退出"
注意:
當(dāng)使用guard
語句進行可選綁定時啥供,可選綁定的常量(let
)、變量(var
)也能在外層作用域中使用
func login(_ info:[String : String]) -> Bool {
guard let username = info["username"] else{
print("用戶名不能為空")
return false
}
guard let password = info["password"] else{
print("用戶密碼不能為空")
return false
}
print("登錄中 username:\(username) password:\(password)")
return false
}
login(["password" : "12345678"])//用戶名不能為空
login(["username" : "Jack"])//用戶密碼不能為空
login(["username" : "Jack", "password" : "12345678"])//登錄中 username:Jack password:12345678
對比使用 if-else
更加簡便
func login2(_ info:[String : String]) -> Bool {
let username:String
if let tempUsername = info["username"] {
username = tempUsername
}else{
print("用戶名不能為空")
return false
}
let password:String
if let tempPassword = info["password"] {
password = tempPassword
}else{
print("用戶密碼不能為空")
return false
}
print("登錄中 username:\(username) password:\(password)")
return true
}
6. 隱式解包
- 在某些情況下库糠,可選項一旦誒設(shè)定后伙狐,就會一直擁有值
- 這種情況下,可以去掉檢查瞬欧,也不必每次訪問的時候都進行解包贷屎,因為它能夠確定每次訪問的時候都有值
- 可以在類型后面加感嘆號!定義一個隱式解包的可選項, 其值不能為
nil
let num1 :Int! = 1 //雖然是隱式解包艘虎,但其仍是可選項
let num2 :Int = num1 //隱式解包可以直接賦值給Int類型
if let k = num1 {
print(k)
}else{
print("nil")
}
7. 多重可選項
結(jié)構(gòu)分析
注意:
可以使用lldb指令:frame variable -R
或者 fr v -R
查看區(qū)別
序號 | 情況1 | 情況2 |
---|---|---|
1 | var n1 : Int? = 10 | var n1 : Int? = nil |
2 | var n2 : Int?? = n1 | var n2 : Int?? = n1 |
3 | var n3 : Int?? = 10 | var n3 : Int?? = nil |
對于情況1:
var n1 : Int? = 10
var n2 : Int?? = n1
var n3 : Int?? = 10
對于情況2:
var n1 : Int? = nil
var n2 : Int?? = n1
var n3 : Int?? = nil
分析:個人覺得??
1. 可選類型 some/none {...}中的內(nèi)容即為盒子里的內(nèi)容唉侄。
2. none 標(biāo)識的是空盒子,當(dāng)為空盒子時野建。下層{}也就不存在意義
3. 對于情況2中 n1 n3都為空盒子属划;n2不是空盒子,盒子里有內(nèi)容候生,內(nèi)容為空