可选类型
- 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而导致运行时错误。