swift - 内存管理

前端之家收集整理的这篇文章主要介绍了swift - 内存管理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

值类型与引用类型

值类型的生命周期仅取决于它的作用域。因此对于值类型不需要考虑内存管理的问题

引用类型(类、函数、closure)的内存管理:
- 大多数由ARC完成
- 没有garbage collerctor

下方中关于内存管理的讨论仅适用于引用类型

举例1

--------- @H_301_16@---------       ---------
|object1|       |object3|       |object4|
--------- @H_301_16@---------       ---------
 | | .@H_301_16@
 |强 |强 .弱@H_301_16@
 |引 |引 .引@H_301_16@
 |用 |用 .用@H_301_16@
 | | .@H_301_16@
 V V V -----------------------------------------@H_301_16@
| object2(RC = 2) | -----------------------------------------@H_301_16@

RC是对对象强引用的计数
当object1或者object3不存在时,RC会自动减少
当RC = 0时,object2会自动释放
object4是否存在对RC没有影响,但当object2不存在时,object4对object2的引用自动变为nil

举例2

-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@  强引用@H_301_16@   -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@  强引用@H_301_16@   -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@
|object1|@H_301_16@ -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@> |object2|@H_301_16@ -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@> |object3|@H_301_16@
-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@           -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@           -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@
                        RC=1@H_301_16@                RC=1@H_301_16@

当object1不存在时,object2和object3都会被释放掉

举例3

RC=2@H_301_16@                RC=1@H_301_16@
-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@  强引用@H_301_16@   -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@  强引用@H_301_16@   -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@
|object1|@H_301_16@ -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@> |object2|@H_301_16@ -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@> |object3|@H_301_16@
-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@           -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@           -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@
                        ^@H_301_16@                   |@H_301_16@
                        |@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@|@H_301_16@
                            强返向引用@H_301_16@

反向引用通常是由于回调函数的使用
当object1不存在时,剩下object2和object3互相引用
它们的空间无法使用(不可达)也无法释放(RC=1),于是造成了内存泄漏

RC=2@H_301_16@                RC=1@H_301_16@
-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@  强引用@H_301_16@   -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@
|object2|@H_301_16@ -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@> |object3|@H_301_16@
-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@           -@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@
    ^@H_301_16@                   |@H_301_16@
    |@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@-@H_301_16@|@H_301_16@
        强返向引用@H_301_16@

因此反向引用必须是weak

举例3

~~~swift

|object1|

|
|

V

|object2 |

|var lastName = “Spook” |
|lazy var greet : ()->() = { |
| print(“Hello (self.lastName)” |

|} |

~~~
这段代码的问题是自引用
对于closure这样的引用类型,赋值相当于设置引用
也就是说,object2的greet : ()->()指向{print("Hello \(self.lastName)"}
而closure中的self.lastname又指向了object2中的lastName

~~~

|object1|

|
|

V

|object2(RC=2) |

|var lastName = “Spook” | <–

lazy var greet : ()->()

V |

|{ |
| print(“Hello (self.lastName)” |

|} |

~~~
解决方案:
使用强引用变为unknown引用

lazy var@H_301_16@ greet : ()@H_301_16@->@H_301_16@() =
{ [unknown self] in@H_301_16@
    print@H_301_16@("Hello \(self.lastName)"@H_301_16@
|}
Capture List

上文中的[unknown self]就是Capture List 如果把self定义为weak,那么必须把self当作是optional的,使用类型let if的语句对使用if 如果把self定义为unknown,那么self不会成为强引用,且能保证self不为空

猜你在找的Swift相关文章