实例对象之间循环强引用
ARC并不是绝对安全的,当两个实例对象间相互强引用,就会造成引用循环,导致所占用的内存无法释放。
class Person{
var name : String
init(personName: String) {
name = personName
}
}
class Student: Person {
var classmate : Student?
override init(personName: String) {
super.init(personName: personName)
}
deinit {
//如果对象被正常释放会调用该方法
print("\(self.name)被正常释放")
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let xiaoHong = Student.init(personName: "xiaoHong")
let xiaoMing = Student.init(personName: "xiaoMing")
//彼此间相互都是对方的同学,造成相互强引用循环
xiaoHong.classmate = xiaoMing
xiaoMing.classmate = xiaoHong
//程序执行到尾部,应该会对该区域内的局部变量进行释放。
}
}
运行起来后,我们可以发现,程序并没有对xiaoHong与xiaoMing两个局部变量进行释放,所以没有打印deinit()方法内的语句。
弱引用解决强引用循环问题
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
weak var xiaoHong = Student.init(personName: "xiaoHong")
weak var xiaoMing = Student.init(personName: "xiaoMing")
//彼此间相互都是对方的同学,造成相互强引用循环
xiaoHong?.classmate = xiaoMing
xiaoMing?.classmate = xiaoHong
//程序执行到尾部,应该会对该区域内的局部变量进行释放。
}
}
在创建实例的时候,将对象声明为弱引用对象就可以防止相互强引用的情况。
当然只声明其中一个为弱引用也是可以的,反正没有造成强引用循环就行。
var xiaoHong = Student.init(personName: "xiaoHong")
weak var xiaoMing = Student.init(personName: "xiaoMing")
//彼此间相互都是对方的同学,造成相互强引用循环
xiaoHong.classmate = xiaoMing
xiaoMing?.classmate = xiaoHong
无主引用解决强引用问题
和弱引用不同的是,无主引用通常都有一个值,因此,无主引用并不可以定义为可选类型。在声明前加关键字unowned可声明为无主引用类型。
class Student: Person {
unowned var classmate : Student?
override init(personName: String) {
super.init(personName: personName)
}
deinit {
//如果对象被正常释放会调用该方法
print("\(self.name)被正常释放")
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let xiaoHong = Student.init(personName: "xiaoHong")
let xiaoMing = Student.init(personName: "xiaoMing")
//彼此间相互都是对方的同学,造成相互强引用循环
xiaoHong.classmate = xiaoMing
xiaoMing.classmate = xiaoHong
//程序执行到尾部,应该会对该区域内的局部变量进行释放。
}
}
运行结果:
xiaoMing被正常释放
xiaoHong被正常释放