可選項(xiàng)(Optional)
可選項(xiàng)误债,一般也叫可選類型浸船,它允許將值設(shè)置為nil
在類型名稱后面加個(gè)問(wèn)號(hào)? 來(lái)定義一個(gè)可選項(xiàng)
var name: String? = "Jack"
name = nil
var age: Int? // 默認(rèn)就是nil
age = 10
age = nil
var array = [1, 15, 40, 29]
func get(_ index: Int) -> Int? {
if index < 0 || index >= array.count {
return nil
}
return array[index]
}
print(get(1)) // Optional(15)
print(get(-1)) // nil
print(get(4)) // nil
強(qiáng)制解包 (Forced Unwrapping)
可選項(xiàng)是對(duì)其他類型的一層包裝,可以將它理解為一個(gè)盒子
如果為nil寝蹈,那么它是個(gè)空盒子
如果不為nil李命,那么盒子里裝的是:被包裝類型的數(shù)據(jù)
var age: Int? // 默認(rèn)就是nil
age = 10
age = nil
- 如果要從可選項(xiàng)中取出被包裝的數(shù)據(jù)(將盒子里裝的東西取出來(lái)),需要使用感嘆號(hào)! 進(jìn)行強(qiáng)制解包
var age: Int? = 10
let ageInt: Int = age!
ageInt += 10
- 如果對(duì)值為nil的可選項(xiàng)(空盒子)進(jìn)行強(qiáng)制解包箫老,將會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤
var age: Int?
age!
Fatal error: Unexpectedly found nil while unwrapping an Optional value
判斷可選項(xiàng)是否包含值
let number = Int("123")
if number != nil {
print("字符串轉(zhuǎn)換整數(shù)成功:\(number!)")
} else {
print("字符串轉(zhuǎn)換整數(shù)失敗")
}
// 字符串轉(zhuǎn)換整數(shù)成功:123
可選項(xiàng)綁定 (Optional Binding)
可以使用可選項(xiàng)綁定來(lái)判斷可選項(xiàng)是否包含值
如果包含就自動(dòng)解包封字,把值賦給一個(gè)臨時(shí)的常量(let)或者變量(var),并返回true耍鬓,否則返回false
if let number = Int("123") {
print("字符串轉(zhuǎn)換整數(shù)成功:\(number)")
// number是強(qiáng)制解包之后的Int值
// number作用域僅限于這個(gè)大括號(hào)
} else {
print("字符串轉(zhuǎn)換整數(shù)失敗")
}
// 字符串轉(zhuǎn)換整數(shù)成功:123
enum Season : Int {
case spring = 1, summer, autumn, winter
}
if let season = Season(rawValue: 6) {
switch season {
case .spring:
print("the season is spring")
default:
print("the season is other")
}
} else {
print("no such season")
}
// no such season
等價(jià)寫法
if let first = Int("4") {
if let second = Int("42") {
if first < second && second < 100 {
print("\(first) < \(second) < 100")
}
}
}
// 4 < 42 < 100
if let first = Int("4"),
let second = Int("42"),
first < second && second < 100 {
print("\(second) < \(second) < 100")
}
// 4 < 42 < 100
while循環(huán)中使用可選項(xiàng)綁定
// 遍歷數(shù)組阔籽,將遇到的正數(shù)都加起來(lái),如果遇到負(fù)數(shù)或者非數(shù)字牲蜀,停止遍歷
var strs = ["10", "20", "abc", "-20", "30"]
var index = 0
var sum = 0
while let num = Int(strs[index]), num > 0 {
sum += num index += 1
}
print(sum)
空合并運(yùn)算符 (Nil - Coalescing Operator)
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T?
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
a ?? b
a 是可選項(xiàng)
b 是可選項(xiàng) 或者 不是可選項(xiàng)
b 跟 a 的存儲(chǔ)類型必須相同
如果 a 不為nil笆制,就返回 a
如果 a 為nil,就返回 b
如果 b 不是可選項(xiàng)涣达,返回 a 時(shí)會(huì)自動(dòng)解包
let a: Int? = 1
let b: Int? = 2
let c = a ?? b // c是Int? , Optional(1)
// a有值,返回a
let a: Int? = nil
let b: Int? = 2
let c = a ?? b // c是Int? , Optional(2)
// a無(wú)值在辆,返回b
let a: Int? = nil
let b: Int? = nil
let c = a ?? b // c是Int? , nil
// a無(wú)值证薇,返回b
let a: Int? = 1
let b: Int = 2
let c = a ?? b // c是Int , 1
// a有值,返回a匆篓,但是b是int浑度,自動(dòng)解包
let a: Int? = nil
let b: Int = 2
let c = a ?? b // c是Int , 2
// a有值,返回a鸦概,b是int箩张,自動(dòng)解包
// 如果不使用??運(yùn)算符
let a: Int? = nil
let b: Int = 2
let c: Int
if let tmp = a {
c = tmp
} else {
c=b
}
多個(gè) ?? 一起使用
let a: Int? = 1
let b: Int? = 2
let c = a ?? b ?? 3 // c是Int , 1
let a: Int? = nil
let b: Int? = 2
let c = a ?? b ?? 3 // c是Int , 2
let a: Int? = nil
let b: Int? = nil
let c = a ?? b ?? 3 // c是Int , 3
?? 跟 if let 配合使用
let a: Int? = nil
let b: Int? = 2
if let c = a ?? b {
print(c)
}
// 類似于if a != nil || b != nil
if let c = a, let d = b {
print(c)
print(d)
}
// 類似于if a != nil && b != nil
if語(yǔ)句實(shí)現(xiàn)登錄
func login (_ info: [String : String]) {
let username: String
if let tmp = info["username"] {
username = tmp
} else {
print("請(qǐng)輸入用戶名")
return
}
let password: String
if let tmp = info["password"] {
password = tmp
} else {
print("請(qǐng)輸入密碼")
return
}
// if username ....
// if password ....
print("用戶名:\(username)", "密碼:\(password)", "登錄ing")
}
login(["username" : "jack", "password" : "123456"] )
login(["username" : "jack") // 請(qǐng)輸入密碼
login(["password" : "123456"] ) // 請(qǐng)輸入用戶名
guard語(yǔ)句
guard 條件 esle {
// do something....
退出當(dāng)前作用域
// return break continue throw error
}
當(dāng)guard語(yǔ)句的條件為false時(shí),就會(huì)執(zhí)行大括號(hào)里面的代碼
當(dāng)guard語(yǔ)句的條件為true時(shí)窗市,就會(huì)跳過(guò)guard語(yǔ)句
guard語(yǔ)句特別合適用來(lái) “提前退出”
當(dāng)使用guard語(yǔ)句進(jìn)行可選項(xiàng)綁定時(shí)先慷,綁定的常量(let、變量(var)也能在外層作用域中使用
func login (_ info: [String : String]) {
guard let username = info["username"] else {
print("請(qǐng)輸入用戶名")
return
}
guard let password = info["password"] else {
print("請(qǐng)輸入密碼")
return
}
// if username ....
// if password ....
print("用戶名:\(username)", "密碼:\(password)", "登錄ing")
}
隱式解包( Implicitly Unwrapped Optional)
在某些情況下谨设,可選項(xiàng)一旦被設(shè)定值之后熟掂,就會(huì)一直擁有值
在這種情況下,可以去掉檢查扎拣,也不必每次訪問(wèn)的時(shí)候都進(jìn)行解包,因?yàn)樗艽_定每次訪問(wèn)的時(shí)候都有值
可以在類型后面加個(gè)感嘆號(hào) ! 定義一個(gè)隱式解包的可選項(xiàng)
let num1: Int! = 10
let num2: Int = num1
if num1 != nil {
print(num1 + 6) // 16
}
if let num3 = num1 {
print(num3)
}
let num1: Int! = nil
// Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
let num2: Int = num1
字符串插值
- 可選項(xiàng)在字符串插值或者直接打印時(shí)素跺,編譯器會(huì)發(fā)出警告
var age: Int? = 10print("My age is \(age)")
- 至少有3種方法消除警告
print("My age is \(age!)")
// My age is 10
print("My age is \(String(describing: age))")
// My age is Optional(10)
print("My age is \(age ?? 0)")
// My age is 10
多重可選項(xiàng)
var num1: Int? = 10
var num2: Int?? = num1
var num3: Int?? = 10
// num2和num3是等效的
print(num2 == num3) // true 二蓝、
- 可以使用lldb指令 frame variable –R 或者 fr v –R 查看區(qū)別 不能是playground
- 空盒子none之后的大括號(hào)就不用看了