Swift:weak与unowned的奥秘

Swift:weak与unowned的奥秘,第1张

以上是 Swift 官方教程中,对 Swift 内存管理的解释。通常情况的部分很好理解,Swift 中 ARC 负责绝大部分的内存管理,ARC部分可以参考我的另一篇博客: iOS内存管理初探 – 引用计数、AutoRelease与ARC ;但少数情况下,我们需要向ARC提供对象之间的关系来使其正确管理内存。那么少数情况是什么意思呢?这得从Swift中的循环强引用讲起。

如图所示的情况中,john指向的对象强引用了unit4A指向的对象,而unit4A指向的对象又强引用了john指向的对象。

paragraph实例有一个成员asHTML强引用了一个闭包,而这个闭包中又捕获了self,意味着对self的强引用。

在ARC下,引用循环的情况是编译器无法自动解决的,这就是上文提到的少数情况。weak 和 unowned 的存才就是为了给编译器提供更多的信息,来打破循环引用。

含义 :weak 即弱引用,当把一个实例声明为弱引用时,此实例不会持有这个对象,即不会使对象的引用计数加1。当对象被废弃,其所有的弱引用会被置为 nil。

适用场景

由于 tenant 是弱引用,当 tenant 引用的对象被销毁(如赋值 nil),tenant 被置为空,并且释放对 apartment的强引用,此时 apartment 所指对象就可以正常释放了。

由于 selfdelegate 指向的是外部对象,生命周期与self无关,所以可能在被捕获后变为nil。(delegate 一般都声明为weak以避免循环引用)

含义无主引用,与弱引用一样,当把一个实例声明为无主引用时,此实例不会持有这个对象,即不会使对象的引用计数加1。但与弱引用不同的是,当对象被废弃,其无主引用并不会被置为 nil。

适用场景

虽然在这个例子中,capitalCity 与 country 的生命周期相同,理论上讲将其中任何一个声明为无主引用都可以打破引用循环,但 capitalCity 与 country 之间有从属关系,所以倾向于将“大”的一方,即 country 声明为无主引用。

self 与属于 self 的成员变量 someClosure 生命周期相同,同时销毁,所以声明为无主引用。

Automatic Reference Counting

在Swift中,写下 unowned 相当于 unowned(safe)。但在官方文档中提到, Swift 还提供了另一种不安全的无主引用 unowned(unsafe) 来禁用运行时的安全检查。运行时的安全检查就是使 unowned(safe) 安全的原因。

unowned(safe) :当访问 unowned(safe) 类型的无主引用时,运行时会进行安全检查,如果对象已经废弃,将抛出异常并终止程序。

unowned(unsafe) :unowned(unsafe) 的作用效果实际上相当于 Objective-C 属性标示符中的 assign/unsafeunretained。访问 unowned(unsafe) 类型的无主引用时,运行时的安全检查被禁用,这时会有三种情况:

The Swift Programming Language (Swift 31) : Automatic Reference Counting
What is the difference in Swift between 'unowned(safe)' and 'unowned(unsafe)'

避免在多个文件中重复import相同的Module
swift中由于有命名空间的存在,在同一个target创建的文件,都可以不引用直接就可以拿来使用,但是不同target之间必须要import 之后才能使用,在不同的文件中使用都要重复的import这个模块

//随便在一个文件中添加自己想要的类库
///MARK:TODO 定义常用的类库信息, 使用@_exported关键字,就可以全局引入对应的包
@_exported import HandyJSON
@_exported import Kingfisher
@_exported import SnapKit
//在其他的文件中就不用再import对应的类库就可以直接使用了

大千世界,求同存异;相遇是缘,相识是份,相知便是“猿粪”(缘分)
From MZou

当UIViewController成为UINavigationController的控制视图,UIViewController的控制视图上的第一个子视图是UIScrollView,UIScrollView会向下位置偏移,影响子控件。

最简单的解决方法是设置UIViewController的automaticallyAdjustsScrollViewInsets属性为NO。

即:selfautomaticallyAdjustsScrollViewInsets = false

您好,宏碁Swift 3是一款轻薄便携的笔记本电脑,通常情况下,我们只需要按下电源键即可开机。但是,如果电脑出现故障或者其他原因导致无法正常开机,我们可以尝试以下方法强制开机:
1 拆卸电池:如果电脑电池可以拆卸,我们可以尝试将电池取出,然后再重新插上电源适配器,按下电源键,看看是否能够开机。
2 按住电源键:有时候电脑出现故障或者其他原因导致无法正常开机,我们可以尝试按住电源键10秒以上,然后再松开,再次按下电源键,看看是否能够开机。
3 清除CMOS:如果电脑出现故障或者其他原因导致无法正常开机,我们可以尝试清除CMOS。具体 *** 作方法可以参考电脑的用户手册或者在网上搜索相关教程。
总之,强制开机是一种应急措施,只有在电脑无法正常开机的情况下才需要使用。如果经常需要强制开机,建议及时联系售后维修人员进行检修。

协议可以通过扩展来为遵循协议的类型提供属性、方法以及下标的实现。通过这种方式,你可以基于协议本身来实现这些功能,而无需在每个遵循协议的类型中都重复同样的实现,也无需使用全局函数。

例如,可以扩展 RandomNumberGenerator 协议来提供 randomBool() 方法。该方法使用协议中定义的 random() 方法来返回一个随机的 Bool 值:

通过协议扩展,所有遵循协议的类型,都能自动获得这个扩展所增加的方法实现而无需任何额外修改:

协议扩展可以为遵循协议的类型增加实现,但不能声明该协议继承自另一个协议。协议的继承只能在协议声明处进行指定。

可以通过协议扩展来为协议要求的方法、计算属性提供默认的实现。如果遵循协议的类型为这些要求提供了自己的实现,那么这些自定义实现将会替代扩展中的默认实现被使用。

例如, PrettyTextRepresentable 协议继承自 TextRepresentable 协议,可以为其提供一个默认的 prettyTextualDescription 属性来简单地返回 textualDescription 属性的值:

注:
1协议,可以继承协议,也可以扩展系统自带协议。
2默认实现:协议只是制定标准接口,不能写具体实现,但可在扩展中写属性和方法的实现。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/13394291.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-07-27
下一篇 2023-07-27

发表评论

登录后才能评论

评论列表(0条)

保存