目录
可选项
可选项,一般也叫可选类型,它允许将值设置为nil
在类型名称后面加个问号 ? 来定义一个可选项
func optionalUse() -> Void {
//1、设置nil
//直接设置 nil会报错
//var name:String = nil
//name可存储两种类型 String和nil
var name:String? = nil
name = "jack"
name = nil
//age可存储两种类型 Int和nil
var age:Int? = nil
age = 18
age = nil
//默认nil
var weight:Int?
weight = 80
weight = nil
//应用
var array = [1,2,3,4]
func get(_ index:Int)->Int?{
if index<0 || index>=array.count {
return nil
}
return array[index]
}
print(get(1))//Optional(2)
print(get(1)!)//2
//对 空 进行解包 会报错 Fatal error: Unexpectedly found nil while unwrapping an Optional value
//print(get(10)!)
print(get(10))//nil
print(get(-1))//nil
}
强制解包
可选项是对其他类型的一层包装,可以将它理解为一个盒子
如果为nil,那么它是个空盒子
如果不为nil,那么盒子里装的是:被包装类型的数据
var age: Int? // 默认就是nil
age = 10
age = nil
如果要从可选项中取出被包装的数据(将盒子里装的东西取出来),需要使用感叹号 ! 进行强制解包
如果对值为nil的可选项(空盒子)进行强制解包,将会产生运行时错误
var age: Int? = 10
let ageInt: Int = age!
ageInt += 10
代码演示
func unwrappingUse() -> Void {
//1、解包
let age2:Int? = 10
//let age22:Int = age2//这么写会报错
let age22:Int = age2! //10
print(age22)
//2、对nil 进行强制解包会报错
let age23:Int? = nil
//print(age23!)//报错
//3、判断可选项是否包含值
let num = Int("123")
if num != nil{
print("字符串转换成功",num!)
}else{
print("字符串转换失败")
}
}
可选项绑定
可以使用可选项绑定来判断可选项是否包含值
如果包含就自动解包,把值赋给一个临时的常量(let)或者变量(var),并返回true,否则返回false
1、if let 会对可选项自动解包
if let num3 = Int("123") {
print("字符串转换成功",num3)
}else{
print("字符串转换失败")
}
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")
}
2、以下两种写法等价
if let first = Int("4") {
if let second = Int("42") {
if first<second && second<100 {
print(first,second)
}
}
}
if let first = Int("4"),
let second = Int("42"),
first<second && second < 100 {
print(first,second)
}
3、while循环中
//遍历数组将遇到的正数加起来,遇到非数字或负数停止遍历
let str = ["10","20","abc","-10","30"]
var sum4 = 0
var index4 = 0
while let num = Int(str[index4]),num>0 {
sum4 += num
index4 += 1
}
print(sum4)
空合并运算符
b 跟 a 的存储类型必须相同
a是可选项 b是可选项 返回可选项
a 非nil 返回 a
a 为nil 返回 b
a是可选项 b非可选项 返回非可选项
a 非nil 返回 a!
a 为nil 返回 b
重点:
a决定了返回谁 b决定了返回什么类型
func emptyMerge(){
//1、基本使用1
print("------------基本使用1_1-------------")
do{
//a是可选项 b是可选项
let a:Int? = 1
let b:Int? = 2
let c = a ?? b
print(c)//Optional(1)
}
//2、基本使用2
print("------------基本使用1_2-------------")
do{
//a是可选项 b是可选项
let a:Int? = nil
let b:Int? = 2
let c = a ?? b
print(c)//Optional(2)
}
//2、基本使用2
print("------------基本使用2_1-------------")
do{
let a:Int? = 1
let b:Int = 2
let c = a ?? b
print(c)//1
}
print("------------基本使用2_2-------------")
do{
let a:Int? = nil
let b:Int = 2
let c = a ?? b
print(c)//1
}
//3、多个 ?? 一起使用
print("------------多个 ?? 一起使用-------------")
do{
let a:Int? = 1
let b:Int? = 2
let c = a ?? b ?? 3
print(c)//1
}
//4、 if let 和 ??配合使用
print("------------if let 和 ??配合使用-------------")
do{
//类似于 if a != nil || b != nil
let a:Int? = nil
let b:Int? = 2
if let c = a ?? b {
print(c)//2
}else{
}
}
do{
let a:Int? = 1
let b:Int? = 2
//类似于 if a != nil && b != nil
if let c = a, let d = b {
print(c,d)//1 2
}else{
}
}
}
guard语句
字典内取出的value是 可选项类型
1、if let 语句实现登录
func login(_ info:[String:String]){
let userName:String
//字典返回的是可选类型 使用时需要解包
if let tmp = info["username"] {
userName = tmp
}else{
print("请输入用户名")
return
}
let passWord:String
if let tmp = info["password"] {
passWord = tmp
}else{
print("请输入密码")
return
}
print("用户名:\(userName)","密码:\(passWord)")
}
login(["username":"jack","password":"123456"])
login(["username":"jack"])
login(["password":"123456"])
2、guard语句实现
//当使用guard语句进行可选项绑定时,绑定的常量let 变量var 也能在外层作用域中使用
func login2(_ info:[String:String]){
/*
guard 条件 else {
// do something....
退出当前作用域
// return、break、continue、throw error
}
当guard语句的条件为false时,就会执行大括号里面的代码
当guard语句的条件为true时,就会跳过guard语句
guard语句特别适合用来“提前退出”
当使用guard语句进行可选项绑定时,绑定的常量(let)、变量(var)也能在外层作用域中使用
*/
guard let userName = info["username"] else {
print("请输入用户名")
return
}
guard let passWord = info["password"] else {
print("请输入密码")
return
}
print("username:\(userName)","password:\(passWord)")
}
login2(["username":"jack","password":"12345"])
login2(["username":"jack"])
login2(["password":"12345"])
login2(["hello":"sss"])
隐式解包
func hideUnWrapping(){
/*
在某些情况下,可选项一旦被设定值之后,就会一直拥有值
在这种情况下,可以去掉检查,也不必每次访问的时候都进行解包,因为它能确定每次访问的时候都有值
可以在类型后面加个感叹号 ! 定义一个隐式解包的可选项
*/
do{
let num1:Int! = 10
let num2:Int = num1
if num1 != nil {
print(num1+6)
}
if let num3 = num1 {
print(num3)
}
}
do{
let a:Int! = nil
//nil无法解包
//报错:Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
//let b:Int = a
}
}
字符串插值
func stringInsert() -> Void {
let age:Int? = 10
print("age is \(age)")
//有几种方法可以消除警告
print("age is \(age!)")
print("age is \(age ?? 0)")
print("age is \(String(describing: age))")
}
多重可选项
func multipleOptional1(){
let num1:Int? = 10
let num2:Int?? = num1
let num3:Int?? = 10
print(num1 == num2)//true
print(num1 == num3)//true
print(num2 == num3)//true
}
func multipleOptional2(){
let num1:Int? = nil
let num2:Int?? = num1
let num3:Int?? = nil
print(num1 == num2)//true
print(num1 == num3)//false
print(num2 == num3)//false
}
可以使用lldb指令 frame variable –R 或者 fr v –R 查看区别
理解:如果两个多重可选项能解包出相同的盒子类型就是相等的可选项
行者常至,为者常成!