可选项
1、定义可选项
在Swift中,默认情况下,不能
给变量设置为空值
;
如果需要赋空值,需要将变量定义为可选类型
;
可选项,一般也叫可选类型,它允许将值设置为nil;
在类型名称后面增加?来定义为可选类型;如:
var str : String? = "QLY"
str = nil
var age : Int? //默认为 nil
age = 20
age = nil
可选类型,是对其他类型的一层包装,可以理解为一个盒子,盒子里包含数据;
如果为nil,就是个空盒子;
如果不为nil,盒子里装的就是被包装的数据类型;
2、强制解包(可选项取值)
获取可选项变量的值,需要对可选项进行强制解包
使用感叹号 !
进行强制解包\
var str : String? = "WL"
print(str!)
注意⚠️:不能对空值进行强解包
var str : String?
print(str!)
判断可选项,是否有值:
var str : String?
if str != nil {
print("有值")
} else {
print("为nil")
}
3、可选项绑定
可以使用可选项绑定
来判断可选项是否包含值;
如果包含,将自动解包,把值赋给临时常量(let)或变量(var),并返回true,否则返回false;
//判断Int("123")是否转换成功,不为nil
if let numner = Int("123")
{
print("字符串转换为整数\(numner)")
}else {
print("字符转转换失败")
}
我们有多重条件判断时,常规的写法是这样的:
if let first=Int("3"){
if let section = Int("34") {
if first < section && section < 100 {
print("条件成功")
}
}
}
但是这样的写法,代码不美观,Swift提供了另一种简洁、等价的写法:
if let first=Int("3"),let section = Int("34"),first < section && section < 100{
print("条件成功")
}
有了这种等价写法,在多重条件判断时,将更加方便使用;
例子:
var numbers = ["12","34","-31","3","6"]
var sum = 0
var index = 0
//循环numbers里的数据,当num < 0的时候,跳出while循环
while let num = Int(numbers[index]),num>0
{
sum += num
index += 1
}
print("sum = \(sum)")
4、隐式可选项
在某些情况下,可选项设值之后,就会一直存在值,不会为空,这种情况下,可以去掉检查,也不必每次访问的时候,都进行解包,因为它能确定一直有值;
那么这种情况,我们可以在类型后面添加!(感叹号)
,定义为隐式可选项;
let num1 : Int! = 1
let num2 : Int = num1
// num1 是隐式可选项,所以可以直接赋值给num2
// 如果num1 是可选项,赋值给num2的时候,需要进行强制解包
使用场景:
- 确保一个常量、变量一直有值的话,在声明常量、变量的时候,可以声明为隐式可选项;
- 注意,隐式可选项,也是可选项,所以
隐式可选项为 nil
的时候,是不能进行强制解包的
5、多重可选项
多重可选项是使用??
来声明
1、注意,多重可选项的 ??
与 空合并运算符的 ??
是不一样的;
2、多重可选项的 ??
是用来定义类型的;
let num1:Int? = 10 //相当于盒子里,包装了一个Int类型的可选类型
let num2:Int?? = num1//相当于盒子里,包装了一个可选类型的可选类型
let num3:Ing?? = 10
图示:
注意⚠️⚠️:如果num1、num2、num3为nil 呢?
let num1:Int? = nil
let num2:Int?? = num1
let num3:Ing?? = nil
那么,num1、num2、num3盒子里,是不一样的;
例题:
let num1:Int? = nil
let num2:Int?? = num1
let num3:Ing?? = nil
1、(num2 ?? 1) ?? 2
答案:2
解答:
先比较:(num2 ?? 1);
num2 = num1,所以num2 不为nil,所以这里返回 num2,但由于1是不可选类型,所以返回num2需要进行解包,解包后得到的值就是num1;
再比较 num1 ?? 2 ,由题可知,num1 = nil,所以直接返回 2;
2、(num3 ?? 1) ?? 2
答案:1
解答:先比较 (num3 ?? 1) ,num3 = nil,直接返回1;
再比较 1 ?? 2,1 不为nil,直接返回 1;
双重强制解包 定义一个多重可选项,可以进行多次解包,由此可以验证,多种可选项,盒子里包含的数据类型
空合并运算符??
1、定义
public func ?? <T>(optional: T?,defaultValue:@autoclosure () throws -> T?) rethrows -> T?
public func ?? <T>(optional: T?,defaultValue:@autoclosure () throws -> T) rethrows -> T
2、使用
a ?? b
- a 必须为
可选项
; - b 可以是
可选项
或者非可选项
; - a、b的存储类型必须相同;
- 如果a 不为 nil,则返回 a;
- 如果a 为 nil,则返回 b;
- 如果b 不是可选项,返回a时将
自动解包
;
let a : Int? = 1
let b : Int? = 2
let c = a ?? b
//当 a != nil,并且为可选项时, c 返回a,是 Int?类型,c = Optional(1)
//当 a = nil,b为可选项时,c 返回 b,是 Int?类型,c = Optional(2)
//当 a != nil,b为不可选项时,c 返回 a,c 自动解包,是 Int类型,c = 1
?? 也可多个一起使用:
let a : Int? = nil
let b : Int? = 2
let c = a ?? b ?? 5
// 先执行 a ?? b ,得到值后,再用得到的 值 ?? 5
guard 条件判断语句
guard语句与if语句一样,都是控制流语句,都是基于表达式的布尔值去判断是否要执行某一段代码;
:
1、guard 语句条件不满足
的时候,才执行大括号里的代码;
2、guard 语句条件为true
时,就会跳出guard语句;
3、guard 语句适合用来提前退出
;
4、guard 语句进行可选项绑定时,绑定的常量(let)、变量(var)也可以在外层作用域中使用;
使用例子:
guard 条件 else {
//do something
//使用如下关键字,可以退出当前作用域
//return、break、continu、throw error
}
//使用guard判断用户名、密码是否存在,login 函数内部,可以使用用户名、密码这两个参数;
func login(_ info:[String:String])
{
guard let username = info["username"] else {
print("请输入用户名")
return
}
guard let passwork = info["passwork"] else {
print("请输入密码")
return
}
print("用户名 = \(username),密码 = \(passwork)")
}