Swift-Optional

295 阅读4分钟

1.可选项(Optional-?)

Swift语言要求所声明的变量属性和常量属性必须有个默认值,常量定义的时候一定带有值,所以对变量提出了Optional概念,在类型名称后面加个问号?来定义一个可选项。

主要格式为:var 变量名:变量类型?var 变量名:变量类型?= 变量值

1.1强制解包(Forced Unwrapping)

从可选项中取出数据,使用感叹号! 举个🌰:

//定义name为可选项
var name : String? = "Chloe"
//强制解包
var rename : String = name!

1.2隐式解包

有些情况下,可选项在定义是会赋一个初始值,这种情况可以不必每次都进行解包,可以在类型后面加个感叹号!定义一个隐式解包的可选项。

主要格式为:var 变量名:变量类型!var 变量名:变量类型! = 变量值 举个🌰:

//定义name为可选项
var name : String!= "Chloe"
//强制解包
var rename : String = name

强制解包感叹号放在变量后面,隐式解包感叹号放在变量类型后面

2.可选项是否有值判断方法

主要介绍可以判断可选项是否有值的几个特别方法;其中可选项绑定包括:if-let、while-let、guard-let。

2.1 三目运算: ? :

主要格式:条件 ? 值1: 值2 满足条件时返回值1,不满足条件时返回值2;

var i : Int?
let ternary = i != nil ? i! : -1
print("Value of i is \(ternary)")//打印结果:Value of i is -1

2.2 if-let:可选项绑定(Optional Binding)

可以使用可选项绑定来判断可选项是否包含值;如果有值就把值赋给一个临时的常量(let)或者变量(var),并返回true,否则返回false;
举个🌰:

var desc: String? = "Optionals"
if let temp = desc{
  print(temp)
}else{
 print("No description")
}
//打印结果:Optionals

附加:
if语句中可以使用逗号分隔多个可选对象:

var optionalX :String? = "x"
var optionalY :String? = "y"
if let x = optionalX, let y = optionalY
{
    print(x) //prints "x"
    print(y) //prints"y"
}
else{
    print("One or more Optional can't be unwrapped")
}

等价于:判断optionalX != nil && optionalY != nil

2.2 while-let:可选项绑定(Optional Binding)

注意:while只要符合条件遍历就会执行,只有遇见不符合条件的情况遍历才会停止,所以while-let慎用,当没有符合条件的数据时,遍历是没办法停止的。 举个🌰:

var strs = ["10","20","abc","-20","30"]
var index = 0
var sum = 0
while let num = Int(strs[index]) ,num > 0{
    sum += num
    index += 1
}
print(sum)//打印结果:30

2.3 ??-空合并运算符(Nil-Coalescing Operator)

主要格式:a ?? b
1)其中a是可选项;
2)b是可选项或者不是可选项;
3)b跟a的存储类型必须相同;
4)如果a不为nil,就返回a;
5)如果b不为nil,就返回b;
6)如果b不是可选项,返回a自动解包;
7)空合并运算结果赋值给常量或变量时,类型一般与??右边的类型相同;
8)多个空合并运算符一起使用时,从左至右依次运算,赋值给常量或变量时常量或变量的类型与最右边的相同。
举个🌰1:

var a : Int? = 10
var b : Int? = 30
var c = a ?? b 
print(c)//打印结果:Optional(10)
print(c!)//打印结果:10;对c进行了强制解包

此时:c类型为Int?;不论是从代码中,还是从注释中都可以看出来。

截屏2021-12-29 上午11.11.12.png 举个🌰2:

var a : Int? = 10
var b : Int = 30
var c = a ?? b
print(c)//打印结果:10

此时:c类型为Int; 截屏2021-12-29 上午11.18.43.png

附加:
??和if-let一起使用例子:

var optionalX :String? = "x"
var optionalY :String? = "y"
if let z = optionalX ?? optionalY
{
    print(z) //打印结果: "x"
}

等价于:optionalX != nil || optionalY != nil

2.4 guard-let

guard语句条件为false时才执行大括号中的代码,大括号中的代码必须要写退出语句,一般形式如下:

guard 条件 else{
  //do something
  退出当前作用域
  //return、break、continue、throw error
}

附加:
1)if-let、while-let语句进行可选项绑定时,绑定的常量、变量不能在外层作用域中使用,可以在内层作用域中使用;
2)guard-let语句进行可选项绑定时,绑定的常量、变量能在外层作用域中使用;但不能在内存作用域中使用
举个🌰:

func testFunc(){
    var a : String? = "a"
    if let c = a {
        print(c)打印结果:a
    }
    print(c)//报错:Cannot find 'c' in scope
}

func testFunc(){
    var a : String? = "a"
    guard let c = a else{
        print(c)//报错:Cannot find 'c' in scope
        return
    }
    print(c)//打印结果:a
}

2.5 属性名+? : 实现可选项绑定

举个🌰:

var num1 : Int? = 5
num1? = 10
print(num1)//打印结果:10


var num1 : Int? = nil
num1? = 5
print(num1)//打印结果:nil

其中num1?会先判断num1是否为nil,不为nil则赋值为10;为nil则不进行赋值。也是一种形式的可选项绑定。

3.Optional本质

Optional本质是枚举,下面是源代码:

@frozen public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none
    case some(Wrapped)
}

所以可选项可以使用Switch-case,举个🌰:

var age : Int? = 10
switch age{
case let .some(v)://等价于case .some(let v)
    print("1",v)
case .none://age为nil时
    print("2")
}