Swift使用自动引用计数(ARC(Automatic Reference Count))来管理应用程序的内存使用。这表示内存管理已经是Swift的一部分,在大多数情况下,你并不需要考虑内存的管理。当实例并不再被需要时,ARC会自动释放这些实例所使用的内存。
内存管理:针对的是实例的内存占用的管理(放在堆里面)
实例:1:由class类型构建的实例,2:闭包对象
下面我们来写一个实例来证明一下
class Person { var name: String init(name: String ) { self.name = name } //类被销毁时,会调用这个方法 deinit { print("\(name) person deinit") } } // var p: Person? = Person(name: "张三") p = nil//"张三" person deinit
当一个事例化的对象被赋予nil的话,会调用的 deinit(),代表着这个对象被销毁
class Person { var name: String init(name: String ) { self.name = name } //类被销毁时,会调用这个方法 deinit { print("\(name) person deinit") } } // var p: Person? = Person(name: "张三") p = Person(name: "banzhang") //"张三persondeinit"
当一个对象引用了另一个新的对象时,旧的对象就会被销毁
func testArc() { var p = Person(name: "chen") print(p.name) } testArc() //chen person deist
如果是一个函数的话, 受作用域的作用, 该对象会被销毁
所以呢,通过上面的几个实例,可以得出如果当一个对象如果没被引用的话,就会自动被销毁
接下来呢, 我们来说一下循环引用,
简单来说呢, 你可以把循环引用当做两个函数里的属性或方法相互调用彼此,这样的话, 很有可能会发生内存泄漏,下面我们来看一下循环引用的解决方法,在说明解决方法时,我们先来说一下两个名词的含义:
空悬指针:(只会出现在弱引用)当指定每一个位置时,该位置存储的数据已经不在。
如果想解决空悬指针的办法只有两种:一种是把其值赋值为nil,另一种是把其指向另外的新对象(这种方法不可行)。
//在swift中,赋值为nil只有用?或!声明的类成员才可以解决空悬指针的问题
//A (a1:B ) B(b1:A)
//? ?
//? !
//! ? (这种情况与上面一样)
//! !
1.两边都是?和 ?
class Student { var name: String var t: Teacher? init(name: String) { self.name = name } deinit { print("\(name) student deinit") } } class Teacher { var name: String weak var banzhang: Student? init(name: String) { self.name = name } deinit { print("\(name) teacher deinit") } } var teacher:Teacher? = Teacher(name: "cj") var bc:Student? = Student(name: "yeweidong") teacher?.banzhang = bc bc?.t = teacher teacher = nil bc = nil //yeweidong student deinit //cj teacher deinit
2.一边为可空类型,一边为非可空类型(unowned)
class Student2 { var name: String var t: Teacher2? init(name: String) { self.name = name } deinit { print("\(name) student deinit") } } class Teacher2 { var name: String //unowned修饰在非可选类型上,不能用weak,weak只能用在可选类型 unowned var banzhang: Student2 init(name: String,stu: Student2) { self.name = name self.banzhang = stu } deinit { print("\(name) teacher deinit") } } var s1: Student2? = Student2(name: "ch") var teac: Teacher2? = Teacher2(name: "david", stu: s1!) s1?.t = teac teac?.banzhang = s1! s1 = nil teac = nil //ch student deist //david teacher deinit
3.两边为非可用类型
class Student2 { var name: String unowned var t: Teacher2 init(name: String ,t :Teacher2) { self.name = name self.t = t } deinit { print("\(name) student deinit") } } class Teacher2 { var name: String //unowned修饰在非可选类型上,不能用weak,weak只能用在可选类型 unowned var banzhang: Student2 init(name: String,stu: Student2) { self.name = name self.banzhang = stu } deinit { print("\(name) teacher deinit") } } var s1: Student2? = Student2(name: "ax", t: teac!)) var teac: Teacher2? = Teacher2(name: "david", stu: s1!) s1?.t = teac teac?.banzhang = s1! s1 = nil teac = nil
两边都是非可用类型的话,无法创建实例,会报错
内存泄露: 当某个对象没有用处时,还占着内存。
关于内存泄漏的话,我们写一个例子循环强引用来看一下
class Student { var name: String var t: Teacher? init(name: String) { self.name = name } deinit { print("\(name) student deinit") } } class Teacher { var name: String var banzhang: Student? init(name: String) { self.name = name } deinit { print("\(name) teacher deinit") } } var teacher:Teacher? = Teacher(name: "cj") var bc:Student? = Student(name: "yeweidong") teacher?.banzhang = bc bc?.t = teacher teacher = nil bc = nil
这样调用的话,不会调用两个类的deinit()。当这两个类没有作用时,还是占着内存, 这就造成了内存泄漏
要解决这种情况的话,
1.使用弱引用
只需要将上述例子Teacher类的banzhang变量加上关键字weak,或者将Student类的t变量加上关键字weak。
class Student { var name: String var t: Teacher? init(name: String) { self.name = name } deinit { print("\(name) student deinit") } } class Teacher { var name: String weak var banzhang: Student? init(name: String) { self.name = name } deinit { print("\(name) teacher deinit") } } var teacher:Teacher? = Teacher(name: "cj") var bc:Student? = Student(name: "yeweidong") teacher?.banzhang = bc bc?.t = teacher teacher = nil bc = nil //yeweidong student deinit //cj teacher deinit
这样调用的话,会调用两个类的deinit()。
好了,内存管理和循环引用就介绍到这里了
来源:https://www.cnblogs.com/zhengyc/p/4979066.html