惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Stack Overflow Blog
Stack Overflow Blog
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
J
Java Code Geeks
C
Check Point Blog
Last Week in AI
Last Week in AI
Microsoft Azure Blog
Microsoft Azure Blog
Blog — PlanetScale
Blog — PlanetScale
月光博客
月光博客
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
L
LangChain Blog
有赞技术团队
有赞技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 司徒正美
IT之家
IT之家
Martin Fowler
Martin Fowler
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tailwind CSS Blog
U
Unit 42
Jina AI
Jina AI
Microsoft Security Blog
Microsoft Security Blog
I
InfoQ

木土金王可

复盘 2024,年度好物分享 落地 第二十台相机:宝丽来(Polaroid)Impulse AF 第十九台相机:哈苏(Hasselblad)X1D II 第十八台相机:宝丽来(Polaroid)Macro 5 SLR 第十七台相机:康泰时(Contax)S2 稻荷山 Dave Chappelle: The Closer 语言是思想的边界 对街头卖惨表演的看法 《民主森林》 电梯英雄 2023,年度好物分享 《大画幅 4x5》复活 新加坡华侨银行(OCBC)开户指南 第十六台相机:宾得(Pentax)PC35AF-M SEDATE 第十五台相机:沙慕尼(Chamonix)4x5 F2 Xbox 连接 Studio Display Twitter、Apple、Meta 和 Reddit 广告平台使用体验 第十四台相机:康泰时(Contax)S2 你到底什么时候买相机 拍摄胶片的理由 HomePod 不能作为 Mac 音响 男性生来就是残缺的女性 第十三台相机:柯尼卡(Konica)Big Mini 301 三年,十二台相机 恐怖片很好看啊 比残忍更残忍 用 SwiftUI 重构「行动日」
什么是自动引用计数(ARC)和引用循环
kinnouka bokudo · 2018-08-28 · via 木土金王可

ARC 全称 Automatic Reference Counting,中文译名为:自动引用计数。通过 ARC 的机制,当创建一个新对象时,它的引用计数为 1,当有一个新的指针指向这个对象时,其引用计数会自动加 1,当某个指针不再指向这个对象时,其引用计数会自动减 1。当对象的引用计数变为 0 时,说明这个对象不再被任何指针指向,然后系统会自动销毁对象,回收内存。

声明:笔者自身对 ARC 也是初学,而本文介绍的 ARC 知识也都是自己的一些理解,同时尽量不涉及过于原理性的内容,一切以普通工程师实用为目标原则。其中可以想象在很多地方会有理解的错误,还请多包涵。如您发现问题,也往不吝赐教指正,感激不尽。

引用循环

得益于 ARC 的工作,开发者不需要太过于关心内存泄露的问题,但是总有意外情况发生。

想象一下,当两个对象已经不再被需要,但这两个对象相互引用了对方作为自己的成员变量,只有当自己销毁时,才会将成员变量的引用计数减 1。由于这两个对象互相引用,所以他们各自的引用计数都为 1,因此这两个对象永远不会被销毁。这种情况称之为强引用循环(Strong Reference Cycle)

弱引用

想要解决这个问题,可以将引用计数对象之间的引用关系指定为弱引用。如果不手动指定,那所有引用都默认会是强引用。

弱引用不会增加对象的引用计数。此外,弱引用始终为可选类型。这意味着当引用计数变为零时,引用可以自动设置为 nil

具体的实现方法就是,在成员变量前加上 weak 修饰符。

无主引用

无主引用也是弱引用,它与弱引用的区别就在于弱引用始终是可选的,并且在引用的对象取消初始化时会自动变为 nil。这就是为什么必须将弱引用的成员变量定义为可选 var类型(因为变量需要更改)。

而无主引用不是可选类型。如果尝试访问已取消初始化对象的无主引用的成员变量,则会触发强制解包 nil 的错误。

与闭包有关的引用循环

当成员变量相互引用时,会出现对象内部的引用循环。与对象一样,闭包也是引用类型,所以也可能会导致循环。

由于闭包对使用它们的对象有一个强引用,所以如果对象对闭包有一个强引用,同时在闭包的代码块中又对该对象本身有一个强引用(比如 self),那这样就会引起引用循环。

解决这个这个问题的方式就是,在闭包内部使用 [unowned self] in 语句,这样就将闭包内部对对象的引用变为弱引用。但是需要注意的是,如果在调用闭包的时候,对象已经被释放的话,会出现错误。或者是使用 [weak self] in 语句,那在闭包内部的 self将变为可选值。

但是这样仍然没有解决在调用闭包时,对象被释放的错误,想要解决这个错误就需要在闭包内部将对对象的应用重新变为强引用,而避免对象在执行过程中被释放。

…{ [weak self] in
    guard let self = self else { return }
    self.somefunc()
}

这种做法的名称为 Weak-Strong Dance,从而就保证了对象在执行过程中不会被释放。

2018 年 8 月 28 日