Swift中有规定:对象中的任何属性在创建对象时,都必须有明确的初始化值。
注意:强制解包是非常危险操作,如果可选类型为nil,强制解包系统会崩溃
建议:在强制解包前,先对可选类型进行判断,判断是否nil
可选项,一般也叫可选类型,它允许将值设置为nil.在类型名称 后面加个问号?来定义一个可选项
var name: String? = "哈哈"
name = nil
var age: Int? //默认就是nil
var array = [1,14,40,29]
func get (_ index:Int) ->Int?{
if index < 0||index >= array.count {
return nil
}
return array[index]
}
print(get(1)) // Optional(14)\
print(get(15)) //越界 nil
print(get(-1))//越界 nil
取数组里面的元素取出来是直实的类型,取字典的值是 可选类型
1、强制解包:
可选项是对其他类型的一层包装,可以将它理解为一个盒子
如果为nil ,那么它是个空盒子
如果不为nil ,那么盒子里装的是: 被包装类型的数据
如果要从可选项中取出被包装的数据,需要使用感叹号!,进行强制解包
如果对值为nil的可选项进行强制解包,将会产生运行时错误。
//判断可选项是否包含值
let number = Int("345")
if number != nil{
print("字符串转换整数成功:\(number!)")
}
else{
print("转换失败")
}
2、可选项绑定
可以使用可选项绑定来判断可选项是否包含值
如果包含就自动解包,把值赋给一个临时的常量(let)或者变量(var),并返回true,否则返回false
if let number = Int("234") {
// number 是强制解包之后的Int值 ,作用域仅限于这个大括号内
print(number)
}
else{
print("失败")
}
enum Season :Int{
case spring = 1, summer,autumn ,winter
}
//rawValue 原始值
if let season = Season(rawValue: 6) {
switch season {
case .spring:
print("spring")
case.summer:
print("summer")
default:
print("ddd")
}
}
else{
print("no such season")
}
//等价写法
if let first = Int("4"){
if let second = Int("42"){
if first < second && second < 100 {
print(first,second);
}
}
}
if let first = Int("4"),let seond = Int("42"),first < seond && seond < 100 {
print("first = \(first),seond= \(seond)")
}
3、while 循环中使用可选项绑定
var strs = ["10","20","30","abc","-50","-60"]
var index = 0
var sum = 0
while let num = Int(strs[index]),num > 0 {
sum += num
index += 1
}
print(sum)
4、 空合并运算符 ??
a ?? b
a 是可选项
b 是可选项 或者 不是可选项
b 跟a的 存储类型必须相同
如果 a 不为nil ,就返回 a
如果 a 为nil , 就返回b
如果 b不是可选项 ,返回a时会自动解包。
let a: Int? = 1
let b: Int? = 2
let c = a ?? b // c 是Int? Optional(1)
print(c)
let a1: Int? = nil
let b1: Int? = 2
let c1 = a1 ?? b1 // c 是Int? Optional(2)
print(c1)
let a2: Int? = nil
let b2: Int? = nil
let c2 = a2 ?? b2 // c是Int? nil, 取的b2值 。
print(c2)
let a3: Int? = 1
let b3: Int = 2
let c3 = a3 ?? b3 // c 是Int 1
print(c3)
let a4: Int? = nil
let b4: Int = 2
let c4 = a4 ?? b4 // c4 Int 2
print(c4)
let a5 :Int? = nil
let b5 :Int = 2
//如果不使用 ??运算符
let c5: Int
if let temp = a5 {
c5 = temp
}else{
c5 = b5
}
5、 多个 ?? 一起使用
let a: Int? = 1
let b: Int? = 2
let c = a ?? b ?? 3
print(c) // c 是Int ,1
let a1: Int? = nil
let b1: Int? = 2
let c1 = a1 ?? b1 ?? 3
print(c1) // c1 是Int 2
let a2: Int? = nil
let b2: Int? = nil
let c2 = a2 ?? b2 ?? 3
print(c2) // c2 是Int 3
6、??跟 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)
}
7、隐式解包!(不用或慎用)
1、在某些情况下,可选项一旦被设定值之后,就会一直拥有值 .
2、在这种情况下,可以去掉检查,也不必每次访问的时候都进行解包,因为它能确定每次访问的时候都有值
3、可以在类型后面加个感叹号! 定义一个隐式解包的可选项
let num1: Int! = 10
let num2: Int = num1
let num3 :Int! = nil
let num4 :Int = num1
8、字符串插值
可选项在字符串插值或者直接打印时,编译器会发出警告
var age :Int? = 10
print("age=\(age)")
// 至少有3种方法消除警告
//1、强制解包
print("age=\(age!)")
//2、String(describing
print("age=\(String(describing: age))")
//3、空合并运算符 ??
print("age=\(age ?? 0)")