内存管理是编程时一个不可回避的问题,在Swift中,是自动管理内存的,也就是ARC机制,自动引用计数机制。我们不需要关心内存的申请和分配。
ARC工作机制
当我们每次创建一个类的新实例的时候,ARC会为我们分配一块内存来存储实例的信息。当该实例不在被使用时即一个实例没有引用的时候,ARC会为我们释放掉所占用的内存,也就是即使清除内存,不造成内存泄露。
如果我们正在使用的实例被ARC回收掉。当我们在此访问的时候会造成崩溃。为了保证真正使用的实例内存不会被回收,ARC会跟踪和计算每一个实例被引用的数量,如果不为0,就不会销毁或回收。
如果想要我们的实例不会被销毁,我们需要创建该类实例的强引用。
循环引用
当两个对象相互强引用对方的时候,其中都不能被释放,就出现了循环引用
class Person:NSObject{
var name:String
init(name:String) {
print("\(name) 被初始化")
self.name = name
}
var car:Car? = nil
deinit {
print("\(name) 被释放")
}
}
class Car:NSObject{
var id:String
init(id:String) {
print("\(id) 被初始化")
self.id = id
}
var person:Person? = nil
deinit {
print("\(id) 被释放")
}
}
var james:Person? = Person(name: "James")
var bmw:Car? = Car(id: "湘B:88888")
james!.car = bmw
bmw!.person = james
// James 被初始化
// 湘B:88888 被初始化
james = nil
bmw = nil
// 并未打印 James 被释放
// 湘B:88888 被释放
上述代码中就出现了循环引用,查找原因。两个对象相互强引用对方,导致谁都无法释放。也就james中间引用了bmw,而bmw中也引用了james,当我们尝试去释放james的时候,由于james的成员变量bmw无法被释放,导致自身也无法被释放。
weak、unowned解决循环引用问题
weak var car:Car? = nil
weak var person:Person? = nil
我们在两个类的成员变量前面加上 weak 关键字,很顺利的得到了我们想要的结果,两个实例被释放。
james = nil
bmw = nil
// James 被释放
// 湘B:88888 被释放
weak: 当一个对象被声明为weak时,表示父层级对改对象没有指向,该对象的ARC 引用计数不会+1。当对象被释放后,弱引用也随即消失。继续访问改对象,程序会得到nil,不会引起崩溃。
unowned: 它与weak的本质是一样的,不同点在于,对象被释放后,依然有一个无效的指向引用,它不是可选,也不是nil,继续访问改对象,会引起奔溃