可選類型
- Swift中所有數據類型聲明的變量或常量都不能爲空值(nil)。
var a3: Int = 10
a3 = nil
let str3: String = nil
- 上面直接給變量或常量賦值爲nil會報錯的,因爲
Int
和String
類型不能接受nil。因此Swift爲每一種數據類型提供一種可選類型
,即每個數據類型後面加上問好(❓)或者歎號(!)。上面變量聲明爲可選類型正確寫法如下:
var a3: Int! = 10
a3 = nil
let str3: String? = nil
Int!
和String?
都是Int
和String
的可選類型,它們可以接受nil。
可選類型值拆包
- 拆包是將可選類型變成普通類型。
let str3: String? = "str"
print(str3)
- 上面可選類型打印結果爲
Optional("str")
,並不是String
類型,所以不能對其進行一些字符串的操作,也不能拼接給其他字符串。 - 因此對可選類型進行拆包是必要的,拆包分爲
顯示拆包
和隱式拆包
。 - 顯示拆包:使用問號(❓)聲明的可選類型在拆包時需要使用歎號(!),這種拆包方式稱爲
顯示拆包
。 - 隱式拆包:使用歎號(!)聲明的可選類型在拆包時可以不使用歎號(!),這種拆包方式稱爲
隱式拆包
。當然也可以使用歎號(!)進行拆包。
var n1:Int? = 10
//顯示拆包
print(n1! + 100)
var n2:Int! = 10
//隱式拆包
print(n2 + 100)
//隱式拆包也可以使用歎號!
print(n2! + 100)
- 隱式拆包的聲明方式通常用於可選類型的值可以確定爲非空的情況。
可選綁定
- 在不能保證可選類型值是否爲非空之前最好不要拆包,否可能出現運行時錯誤。
func divide(n1:Int,n2:Int) -> Double? {
if n2 == 0{
return nil
}else{
return Double(n1)/Double(2)
}
}
let result = divide(n1: 1000, n2: 0)
print(result!) //報錯
上面result是值爲空(nil)的可選類型,如果沒有判斷就拆包運行時是會報錯的,報錯如下:
報錯原因還是因爲拆包後的普通類型是不能接受nil。
- 我們可以判斷可選類型值是否爲nil來決定是否拆包:
方式1:
if result != nil {
print(result!)
}
方式2:
if let result2 = divide(n1: 1000, n2: 0){
print(result2)
}else{
print("failure")
}
- 其中方式2就是可選綁定。
- 可選綁定:可選類型在if或while語句中賦值並進行判定的寫法稱爲
可選綁定
。可選綁定做了兩件事情:首先判斷表達式值是否爲空(nil),如果爲非空就將可選類型值拆包並賦值給一個常量;常量的作用域是if或while語句爲true的分支。(所以方式2中result2在else之前有效,之後則無效)。
可選鏈
class Employee{
var name = ""
var no = 0
var job = ""
var dept: Department?
}
class Department{
var no = 10
var name = "Sales"
var comp: Company?
}
class Company {
var no = 888666
var name = "阿里巴巴"
}
let emp = Employee()
//print(emp.dept!.comp!.name) //直接報錯
print(emp.dept?.comp?.name as Any)
emp.dept = Department()
emp.dept?.comp = Company()
print(emp.dept!.comp!.name)
print(emp.dept?.comp?.name as Any)
可見直接顯示拆包如果可選鏈中摸個值爲nil,會導致代碼運行時錯誤。使用?代替!的位置,如果某個環節爲nil,不會報錯,而是會吧nil給引用者,如果有值就是一個可選值,我們可以根據可選綁定再做進一步的判斷處理。這種由問好(?)引用可選類型的方式就是可選鏈
。
- 可選鏈是一種溫柔的引用方式,它引用的目標不僅僅是屬性,還可以是方法、下表、嵌套類型等。
使用?和!的含義
- 可選類型中的?:聲明這個類型是可選類型,訪問這種類型的變量或常量需要用!解包。(顯示聲明可選類型)
- 可選類型中的!:聲明這個類型是也是可選類型,訪問這種了星星的變量或常量可以不需要用!解包。(顯示聲明可選類型)(隱示聲明可選類型)
- 可選鏈中的!:溫柔的訪問引用可選類型,避免可選鏈中因爲出現nil而導致運行時錯誤。