Swift中的可选链与内存管理(干货系列)

干货之前:补充一下可选链(optional chain)

 1 class A {
 2     var p: B?
 3 
 4 }
 5 
 6 class B
 7 {
 8     var p: C?
 9 }
10 
11 class C {
12     func cm() -> String {
13         print("cm")
14         return "abc"
15     }
16 }
17 
18 let insa = A()
19 let insb = B()
20 let insc = C()
21 insa.p = insb
22 //insa.p = nil
23 insb.p = insc
24 
25 let r = insa.p?.p?.cm()

解析:此处定义了A,B,C三个类,使其依次关联,最后通过类A实例的属性拿到B实例,依次拿到C实例再调用C的方法。

注意:1,中间任何一个地方为nil,不报错,但导致整个结果为nil。

2,如果没有一个地方为nil,整个表达式才正常执行。

内存管理

swift中的或者java,c#语言的内存管理,指的就是引用类型对象的管理,也就是对“堆(heap)”里面的对象的管理。

这三种语言中,值类型不需要进行内存管理,值类型是放在栈里的,程序会自动管理,不需要特别的机制。

swift中的内存管理技术,叫做arc,自动引用计数(Auto Reference Count) 当对对象的引用计数为0时,立即销毁对象

这种管理一般会产生两种错误可能

1.空引用

2.内存泄露(leak) 某个时候,某些对象分配了内存,但因为某些原因,导致程序结束时,此对象所占的内存没有被回收

我们可以控制的引用计数的数量 增加的方法 1.声明变量,指向某个对象(直接new或者把别的变量的值赋值给你 )

减少的方法

1.f = nil(表示不指向任何东西)

2.变量一般会运行在函数中,变量本身是存放在栈中的 所以函数结束时,此变量消失

关于循环引用swift提供了两种方法来解决,

一种是weak(弱),一种是unowned(未拥有)

1.weak 可以修饰在可为空(?,!)的属性上

2.unowned只能修饰在非可为空的属性上。

循环引用案例

 1 class A {
 2     var p: B?
 3     init() {
 4         print("a********************")
 5     }
 6     deinit {
 7         print("a--------------------")
 8     }
 9 }
10 
11 class B{
12     var p: A?
13     init() {
14         print("b********************")
15     }
16     deinit {
17         print("b--------------------")
18     }
19 
20 }
21 var f1:A? = A()
22 var f2:B? = B()
23 //使用这两个类时,可以从控制台看到这两个类已经初始化完毕
24 //通过f1f2两个对象的属性将这两个类相互关联
25 f1?.p = f2
26 f2?.p = f1
27 //此时再将这两个对象赋值为nil
28 //f1 = nil
29 //f2 = nil
30 //但此时并没有调用类的析构函数
31 //原因:f1f2这两个对象的属性相互引用了这两个对象
32 f1?.p = nil
33 f2?.p = nil
34 f1 = nil
35 f2 = nil

解析:1,此处现将f1f2两对象的属性赋值为nil再将f1f2赋值为nil即代表A,B这两个类完全没有引用,此时才会调用析构函数,回收内存。

2,以上这种循环引用的问题,对象并没有真正清除常常会导致内存泄漏(leak)

解决方法一:weak

 1 class C {
 2     var p: D?
 3     init() {
 4         print("c********************")
 5     }
 6     deinit {
 7         print("c--------------------")
 8     }
 9 }
10 
11 class D{
12     weak var p: C?
13     init() {
14         print("d********************")
15     }
16     deinit {
17         print("d--------------------")
18     }
19     
20 }
21 var f3:C? = C()
22 var f4:D? = D()
23 f3 = nil
24 f4 = nil

此时发现在任何一个循环引用的属性上加上weak关键字,即可解决上述问题

注意:weak 可以修饰在可为空(?,!)的属性上

解决方式二:unowned

 1 class E {
 2     var p: F?
 3     init() {
 4         print("e********************")
 5     }
 6     deinit {
 7         print("e--------------------")
 8     }
 9 }
10 
11 class F{
12     unowned var p: E
13     init(a:E) {
14         p = a
15         print("f********************")
16     }
17     deinit {
18         print("f--------------------")
19     }
20     
21 }
22 var f5:E? = E()
23 var f6:F? = F(a:f5!)
24 f5 = nil
25 f6 = nil

注意:unowned只能修饰在非可为空的属性上。

原文地址:https://www.cnblogs.com/1016882435AIDA/p/6102030.html