Swift-可选链

可选类型

可选类型的本质其实就是一个枚举,

None Some
没有值 有值

格式:Optional<类型> 或 在类型后面加上?号

由于可选类型在Swift随处可见,所以系统做了一个语法糖,在类型后面加上?

具体介绍可看之前的文章Swift-元祖、可选值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var opa: Optional<Int>
var opb: Int?

var nora: Int
nora = 11
/*
基本类型变量,在使用之前必须进行初始化,否则报错
目的:安全,不管在什么时候访问都是有意义的
普通变量和可选类型的区别,普通变量只有一种状态,有值
注意:Swift的变量和C/OC的不一样,C/OC可以没有值,是一个随机值
*/

print(nora)

/*
由于普通变量只有一种状态,有局限性,所以Swift设计了可选类型
可选类型是安全的么?是,可以通过可选绑定判断后再使用
Swift的发明者完全是基于安全的考虑,当我们使用基本类型时完全不用考虑是否有值
当我们使用可选类型时,总会记得先判断再使用,让程序时刻了解那些有值哪些没有值
*/

opb = 26
if let b = opb{
// print(opb!)
print(b)
}

// Swift中的可选类型变量更贴近OC中的普通变量
//NSData *data = [NSData dataWithContentsOfMappedFile:@"/Users/fty/Downloads/接口签名算法.txt"];
//NSLog("%@", data);

var data:NSData? = NSData(contentsOfFile: "/Users/fty/Downloads/接口签名算法.txt")
if let da = data {
print(da)
}

可选链

可选链(Optional Chinaning)是一种可以请求和调用属性、方法和子脚本的过程,用于请求或调用的目标可能为nil

可选链返回有两个值:

  • 如果目标有值,调用将返回该值
  • 如果目标为nil,嗲用将返回nil

多次请求或调用可以被链接成一个链,如果任意一个节点为nil将导致整条链失效。

注意:可选链的返回值是一个可选值

格式:

  • 可选值?.属性
  • 可选值?.方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Person {
var name: String
init(name:String) {
self.name = name
}
func description() ->String{
print("my name is \(self.name)")
return name
}
}
var p1: Person?
var p2: Person = Person(name: "daisuke")

p2.name = "alex"
p2.description()

// 如何通过可选类型来调用对应的方法和属性

// 1、通过强制解包(但是强制解包非常危险,如果可选类型没有值,会引发运行时错误)
//p1!.name = "rose"
//p1!.description()

// 2、通过可选绑定,代码繁琐
//if let p = p1{
// p.name = "rose"
// p.description()
//}

// 3、通过可选链,如果问号前面的变量没有值,整个可选链会失效(代码更加简洁,有利于使用可选类型)
p1 = p2
p1?.name = "rose"
p1?.description()

/*
可选链的返回值会自动包装成一个可选值
因为可选链可能失效,所以返回值可能有值也可能没有值,要想表达有值或者没有值只能用可选值,所以返回值会自动包装成一个可选值
*/

if let name = p1?.name{
print(name)
}
if let description = p1?.description(){
print(description)
}

可选链调用下标索引

格式:可选值?[]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
struct Student {
var name:String = "daisuke"
var math:Double = 99.3
var chinese:Double = 100.0
var english:Double = 83.3

/*
要想实现下标访问,必须实现subscript方法
如果想要通过下标访问,必须实现get方法
如果想要通过下标赋值,必须实现set方法
*/

subscript(course:String) ->Double?{
get{
switch course{
case "math":
return math
case "chinese":
return chinese
case "english":
return english
default:
return nil
}
}
set{
switch course{
case "math":
// 因为返回的是可选类型
math = newValue!
case "chinese":
chinese = newValue!
case "english":
english = newValue!
default:
print("not found")
}
}
}

}
var stu:Student? = Student()
// 可选链调用下标索引不需要.,直接在问号后面写上[]即可
print(stu?["math"])

//var arr:Array? = [1,2,3,4,5]
//print(arr?[2])

// 利用可选链赋值,注意:早版本中不能使用可选链赋值
stu?.name = "daisukeiti"
print(stu?.name)

// 利用可选链给下标赋值
stu?["math"] = 99.9
print(stu?["math"])

// 判断赋值操作是否成功,可选链的赋值操作也有返回值
// 如果赋值成功返回一个可选类型,返回()? 也就是Viod? 代表成功。返回nil代表失败
let res1: ()? = stu?.name = "alex"
print(res1) // Optional(())

let res2: Void? = stu?.name = "alex"
print(res2) // Optional(())

// 把stu赋值nil
stu = nil
let res3: Void? = stu?.name = "alex"
print(res3) // nil

多层可选链

单层:可选值?.属性

多层:可选值?.属性.属性?.属性 or 可选值?.属性?.属性?.属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class A {
var name:String = "daisuke"
}
class B {
var a:A?
}
class C {
var b:B = B()
}
class D {
var c:C?
}

var a1 = A()
var b1 = B()
var c1 = C()
var d1 = D()

// d1访问c,由于c没有赋值,那么c=nil
print(d1.c) // nil

// 给c赋值
d1.c = c1

// 可选链赋值
// 由于D中的C是可选值,所以需要在C后面加上?
d1.c?.b.a = a1

// 通过d1直接获取a1中的name
// 其实只需要在可选值后面加上问号即可,如果可选值不存在,那么后面的链就会失效
print(d1.c?.b.a?.name)// Optional("daisuke")

参考: