大佬教程收集整理的这篇文章主要介绍了Swift(十六、自动引用计数),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
1、Swift入门学习笔记(第一版),对Swift的基础知识点进行梳理总结。知识点一直在变,只是作为参考,以苹果官方文档为准~
2、在学习完基本的知识点以后会结合官方文档及相关资料,在此版本的基础上进行添加更改。
引用计数仅适用于类实例。结构体和枚举类型是值类型,不是引用类型,不是通过引用方式存储和传递
与OC大同小异,此处不累述
class Person {
init() {
print("Init")
}
deinit {
print("Deinit")
}
}
var reference1:Person?
var reference2:Person?
var reference3:Person?
//定义为可选类型是为了可赋nil
reference1 = Person() //输出Init
reference2 = reference1 //无输出
reference3 = reference1 //无输出
//赋值nil,断开强引用
reference1 = nil //无输出
reference2 = nil //无输出
reference3 = nil //输出Deinit
与OC大同小异,此处不累述
Swift提供两种解决循环引用的问题:弱引用(weak reference)和无主引用(uNowned reference)
在生命周期内会变为nil
的实例使用弱引用。对初始化赋值后不会被赋值为nil
的实例使用无主引用
a、weak
关键字表示弱引用,一方强一方弱
b、必须声明为变量,表示其值在运行时可修改
c、必须声明为可选类型,因为弱引用可为nil
class Person {
var pet:Dog?
deinit {
print("Person deinit")
}
}
class Dog {
weak var owner:Person?
deinit {
print("Dog deinit")
}
}
//可选类型,@L_772_19@人可以有狗也可以没狗,一只狗可以有主人也可以是流浪狗
//建立引用关系
var person:Person? = Person()
var pet:Dog? = Dog()
person!.pet = pet
pet!.owner = person
person = nil //person的引用计数为0,person被释放,pet引用计数变为2
pet = nil //pet引用计数变为0
Output:
Person deinit Dog deinit
注意:在使用垃圾收集的系统里,弱指针有时用来实现简单的缓存机制,因为没有强引用的对象只会在内存压力触发垃圾回收时才被销毁,但在ARC中一旦不被强引用,就会被立刻销毁,因此不适合用来实现缓存
a、uNowned
表示无主引用
b、无主引用永远有值
c、总是被定义为非可选类型
class Person {
var pet:Dog?
deinit {
print("Person deinit")
}
}
class Dog {
uNowned let owner:Person
init(owner:Person) {
self.owner = owner
}
deinit {
print("Dog deinit")
}
}
//可选类型,@L_772_19@人可以有狗也可以没狗,但是狗必须要有主人
var person:Person?
person = Person()
person!.pet = Dog(owner: person!)
//person引用计数为1,dog引用计数也为1只有person引用它
person = nil
//person为nil,那么没有指向Person实例的强引用,实例被销毁。之后,指向Dog实例的强引用也没了,该实例随之被销毁
Output:
Person deinit Dog deinit
前面阐述了两个实例均可以为nil的情况使用弱引用,以及其中一方为nil使用无主引用。
接下来阐述两方都必须有值,均不能为nil
的情况
解决方法:@L_772_19@类使用无主属性,另@L_772_19@类使用隐式解析可选属性
实际上操作跟上面的一样,就是?
改成!
,表示不能为nil
即可
class Person {
var pet:Dog!
init(petName:string) {
self.pet = Dog(name: petName,owner: self)
print("Person init")
}
deinit {
print("Person deinit")
}
}
class Dog {
let name:string
uNowned let owner:Person
init(name:string,owner:Person) {
self.name = name
self.owner = owner
print("Dog init")
}
deinit {
print("Dog deinit")
}
}
var person = Person(petName: "Lucky")
//person.pet可以被访问,不用!展开
print(person.pet.Name)
Output:
Dog init Person init Lucky
如果闭包定义在类内部,而类又引用了实例的属性或者方法(捕获),产生循环引用
解决方案:闭包捕获列表
class Person {
var name:String
lazy var printName:Void -> Void = {
print(self.Name)
}
init(name:String) {
self.name = name
}
deinit {
print("Deinit")
}
}
//lazy延迟加载,只有当类实例构造完成之后才得到,不加无法使用self
var p:Person? = Person(name: "Zane")
p = nil
Output:
Deinit
由打印结果可知,p实例销毁了,因为闭包只有在使用的时候才会初始化,因此这里没有循环引用
接下来使用闭包
var p1:Person? = Person(name: "Zane")
p1!.printName()
p1 = nil
Output:
Zane
打印结果并没有Deinit,循环引用,实例未释放
解决方法:定义捕获列表,声明每个捕获的引用为弱引用或者无主引用
a、包含参数列表和返回类型,把捕获列表放前面,以及一些初始化的变量例如delegate等,逗号隔开
lazy var test:(Int,String) -> String = {
[uNowned self,weak delegate = self.delegate!](index:Int,String:string)->String in
//闭包操作
}
b、无指明参数类型或者返回值,即使有也可以不写,编译器自己推断
lazy var printName:Void -> Void = {
[uNowned self] in print(self.Name) }
这里修饰符weak还是uNowned前文已讲
以上是大佬教程为你收集整理的Swift(十六、自动引用计数)全部内容,希望文章能够帮你解决Swift(十六、自动引用计数)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。