Swift知识基础复习最后一章

类的闭包初始化器{}()

1
2
3
4
5
6
7
8
9
import Cocoa

class A {
var age: Int = {
var a = 10
var b = 20
return a + b
}()
}

反初始化器deinit

被销毁时运行的初始化器

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
import Cocoa

class A {
var name: String

init(name: String) {
self.name = name
}

deinit {
print("\(self.name)被销毁")
}
}

var t1: A? = A(name: "hello")
var t2 = t1
var t3 = t1

/*

*/

t1 = nil
t2 = nil
t3 = nil

/*
hello被销毁
*/

var t: A? = A(name: "world")
t = nil

/*
world被销毁
*/

循环强引用

想要销毁对象需要断开所有指向他的强引用

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
import Cocoa

class TestA {
var name: String

var ref: TestB? = nil //循环强引用

init(name: String) {
self.name = name
}

deinit {
print("TestA的实例被释放 - " + self.name)
}
}

class TestB {
var name: String

var ref: TestA? = nil //循环强引用

init(name: String) {
self.name = name
}

deinit {
print("TestB的实例被释放 - " + self.name)
}
}

var testA: TestA? = TestA(name: "hello")
var testB: TestB? = TestB(name: "world")
testA?.ref = testB //循环强引用
testB?.ref = testA //循环强引用

//需要销毁对象需要断开所有指向该对象的引用
testB?.ref = nil //销毁了指向对象A的对象B中的引用
testA = nil //销毁了指向对象A的引用

/*
TestA的实例被释放 - hello
*/

弱引用weak

想要销毁对象需要断开所有指向他的引用

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
import Cocoa

class TestA {
var name: String

var ref: TestB? = nil //循环强引用

init(name: String) {
self.name = name
}

deinit {
print("TestA的实例被释放 - " + self.name)
}
}

class TestB {
var name: String

weak var ref: TestA? = nil //弱引用weak

init(name: String) {
self.name = name
}

deinit {
print("TestB的实例被释放 - " + self.name)
}
}

var testA: TestA? = TestA(name: "hello")
var testB: TestB? = TestB(name: "world")
testA?.ref = testB
testB?.ref = testA

//需要销毁对象需要断开所有指向该对象的强引用
//testB?.ref = nil //销毁了指向对象A的对象B中的引用 //弱引用无需断开
testA = nil //销毁了指向对象A的引用

/*
TestA的实例被释放 - hello
*/

无主引用unowned

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
import Cocoa

class TestA {
var name: String

var ref: TestB? = nil //循环强引用

init(name: String) {
self.name = name
}

deinit {
print("TestA的实例被释放 - " + self.name)
}
}

class TestB {
var name: String

unowned var ref: TestA //无主引用需要有值,不能为空(和弱引用区别)

init(name: String, ref: TestA) {
self.ref = ref
self.name = name
}

deinit {
print("TestB的实例被释放 - " + self.name)
}
}

var testA: TestA? = TestA(name: "hello")
var testB: TestB? = TestB(name: "world", ref: testA!)
testA?.ref = testB

//需要销毁对象需要断开所有指向该对象的强引用
//testB?.ref = nil //销毁了指向对象A的对象B中的引用 //无主引用无需断开
testA = nil //销毁了指向对象A的引用

/*
TestA的实例被释放 - hello
*/

闭包循环引用 定义捕获列表{[unowned self]() -> }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import Cocoa

class A {
var name: String

lazy var rank: () -> Void = {[unowned self]() -> Void in //使用延迟属性是为了防止初始化之前不能调用 //定义捕获列表,将self变为无主引用
print("打印了 - " + self.name) //闭包内使用了self引用了内部属性导致无法被释放,所以需要定义捕获列表
}

init? (name: String) {
self.name = name
}

deinit {
print("已被销毁" + self.name)
}
}

var a: A? = A(name: "hello")

a!.rank()

a = 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
44
45
46
47
48
49
50
import Cocoa

func a (param1: String, param2: (String) -> Void) {
param2(param1 + " - swift")
}

a(param1: "hello", param2: {(data: String) -> Void in
print(data)
})

/*
hello - swift
*/

//尾随闭包是函数在最后一项的时候可以将函数写在括号外面

a(param1: "world") { (data: String) -> Void in
print(data)
}

/*
world - swift
*/


//例子
import Cocoa

func b (param: (String) -> String) {
let t = param("hello")
print(t)
}

b(param: {(a: String) -> String in
return a + "经过添加"
})

b() { (a: String) -> String in
return a + "经过二次添加"
}

b { (a: String) -> String in
return a + "经过三次添加"
}

/*
hello经过添加
hello经过二次添加
hello经过三次添加
*/

错误枚举及错误捕获

错误捕捉

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
import Cocoa

enum TestError: String,Error {
case error1 = "错误一"
case error2 = "错误二"
}

func test(num: Int) throws -> String{
if num < 5 {
throw TestError.error1
}else if (num >= 5) && (num < 10) {
throw TestError.error2
}
print("正常执行")
return "hello world"
}

do {
let a = try test(num: 8)
print(a)
} catch TestError.error1 {
print(TestError.error1.rawValue)
} catch TestError.error2 {
print(TestError.error2.rawValue)
}
defer {
print("收尾工作")
}

/*
错误二
收尾工作
*/

//也可以使用可选类型的方式来处理

var b = try? test(num: 8)
print(b != nil ? b![]: "unknown")

/*
unknown
*/

泛型

可以用一个代码来代替各种类型

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
 func todoit<T>(param: T) -> T {
return param
}

print(todoit(param: "hello"))
print(todoit(param: 123))
print(todoit(param: [1,2,3]))
print(todoit(param: 1.1))

/*
hello
123
[1, 2, 3]
1.1
*/

//也可以添加泛型的类型

import Cocoa

class Data {
var name: String

init(name: String) {
self.name = name
}
}
func todoit<T: Data>(param: T) {
print(param.name)
}

todoit(param: Data(name: "hello"))

/*
hello
*/

协议protocol

类必须要遵守协议

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
import Cocoa

class A {

}

protocol Protocol1 {
var a1: String { get set }
func b1() -> String
}

protocol Protocol2 {
var a2: String { get }
func b2() -> String
}

class B: A, Protocol1, Protocol2 {
var a1: String
var a2: String

func b1() -> String {
return a1
}

func b2() -> String {
return "hello world"
}

init(a: String) {
self.a1 = a
self.a2 = a
}
}

var a = B(a: "swift")

print(a.a1)
print(a.a2)
print(a.b1())
print(a.b2())

//协议中可以添加类似泛型的关键词
import Cocoa

protocol Test {
associatedtype D

func play(param: D)
}

class Name: Test {
func play(param: String) { //可以用任意类型代替协议中的D
print(param)
}
}

var xiaoming = Name()
xiaoming.play(param: "hello")
/*
hello
*/

必要初始化器required

父类要求子类必须有该初始化器用到required

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 import Cocoa

class A {
var name: String

required init(name: String) {
self.name = name
}
}

class B: A {
required init(name: String) {
super.init(name: name)
}
}

var a = B(name: "hello")
print(a.name)

参考资料

Swift编程基础