********内存管理基础*********************
内存管理:针对的是实例的内存占用的管理(放在堆里面)
实例:1:由class类型构建的实例,2:闭包对象
内存管理技术:ARC:Automatic Reference Count
自动:由语言本身帮我们销毁内存,不需要你手动销毁,
比如在c中就调用dealloc()
引用:let p = Person() p就是对Person()这个对象的一个引用
计数: let p = Person() //一个
/ / let pp = p //二个
利用析构函数来判断是否销毁
class Person { var name: String init(name: String ) { self.name = name } deinit { print("\(name) person deinit") } } var p: Person? = Person(name: "david") //p = nil var pp = p p = nil pp = Person(name: "banzhang") pp = nil
引用增加:一般是把一个对象不断的赋值给变得变量或属性等
引用减少:手动把变量等得值赋值为nil活着让其引用一个新的对象,活着函数执行完毕(比如下面)
class Person { var name: String init(name: String ) { self.name = name } deinit { print("\(name) person deinit") } } func testArc() {
var p = Person(name: "chenhe") print(p.name) } testArc() //系统自动调用deinit
*************循环引用*************
循环引用的阐述
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: "cheng") var bc:Student? = Student(name: "ling") teacher?.banzhang = bc bc?.t = teacher teacher = nil bc?.t = nil bc = nil //因为是两个强引用,所以还要bc?,t=nil
//循环引用的解决办法:weak(弱引用)和unowned(非拥有)
循环引用:为了解决内存泄露与空悬指针的问题
解决空悬指针的办法只有两种:一种是把其值赋值为nil,另一种是把其指向另外的新对象(这种方法不可行)
在swift中,赋值为nil只有用?或!声明的类成员才行
严格来说,就只有3种情况需要考虑
**********第一种情况:两边都是?
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 bc = nil teacher = nil //因为teacher是weak
第二种情况:一边为可空类型,一边为非可空类型(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
第三种情况
//第三种情况:两边都是非可空类型 class Student3 { var name: String var t: Teacher3! //nil init(name: String,teacherName: String) { self.name = name//这行代码运行后name有值,然后t有nil,所以self就可以用 self.t = Teacher3(name: teacherName, stu: self) } deinit { print("\(name) student deinit") } } class Teacher3 { var name: String // var banzhang: Student3 = Student3(name: "xuesheng", teacher: self)//不能用self,除非lazy unowned var banzhang: Student3 init(name: String,stu: Student3) { self.name = name self.banzhang = stu } deinit { print("\(name) teacher deinit") } }
//如果两个类中,其属性都是非可空类型,并且互相引用
//那么会导致这两个对象永远不能创建出来
var s3: Student3? = Student3(name: "xxx", teacherName: "zhuzhu")
var t3 = Teacher3(name: "zhuzhu", stu: s3!)
s3?.t = nil
s3 = nil
循环引用在闭包中的体现
class ClosureClass { var name = "asdf" //利用方括号语法(捕获列表)来处理循环引用 //多个之间用逗号分隔 lazy var myClosure:Void->Int = { //[unowned self] //直接修饰unowned或weak [unowned this = self]//除了修饰以外,还可以取别名 //[unowned this = self,unowned self] ()-> Int in print(this.name) print(self.name) return 5 } deinit { print("closer deinit") } } //有两个对象,一个是ClosureClass对象,一个是闭包对象 var cc: ClosureClass? = ClosureClass() cc?.myClosure() cc = nil cc?.myClosure() //输出nil,说明已被销毁