/**
构造器的补充:(类的构造需要两个阶段)
阶段一
1.程序调用子类的某个构造器
2.为实例分配内存,此时实例的内存还没有被初始化;
3.指定构造器确保子类定义的所有实例存储属性都已经被赋初值
4.指定构造器将调用父类的构造器,完成父类定义的实例存储属性的初始化
5.沿着调用父类构造器的构造器链一直往上执行,直到到达构造器链的最顶部。
阶段二
1.沿着继承树往下,构造器此时可以修改实例属性、访问self,甚至可以调用实例方法;
2.最后,构造器链中的便利构造器都有机会定制实例和使用self。
*/
import UIKit
var reference1:Person?
var reference2:Person?
var reference3:Person?
class Person{
let name:String
init(name:String){
self.name=name
print("\(name) is being init")
}
deinit{
print("\(name) is being deinit")
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//自动引用计数
//Swift 使用自动引用计数机制来跟踪和管理应用程序内存,arc 会在类的实例不在被使用时,自动释放其占用的内存
reference1=Person(name: "DLG")//DLG is being init
//由于Person类的新实例被赋值给了reference1变量,所以reference1到Person类的新实例之间建立了一个强引用
reference2=reference1
reference3=reference1
reference1=nil
reference2=nil
reference3=nil //DLG is being deinit
//arc会跟踪你所新创建的Person实例的引用数量,并且会在Person实例不在被需要时销毁它
//类实例之间的循环强引用
//如果两个类实例互相持有对方的强引用,因而每个实例都让对方一直存在,这种情况下就是所谓的循环强引用
//可以通过定义类之间的关系为弱引用或无主引用,以代替强引用,从而解决循环强引用的问题
john=myPerson(name: "john Appleseed")
unit4A=Apartment(unit: "4A")
john!.apartment=unit4A//注意:感叹号是用来展开和访问可选变量john和unit4A中的实例,这样实例的属性才能被赋值
unit4A!.tenant=john
//这俩个实例关联后会产生一个循环引用。myPerson实例现在有了一个指向Apartment实例的强引用,而Apartment实例也有一个指向myPerson实例的强引用,因此当你断开join和unit4A变量所持有的强引用时,引用计数并不会降为0。
john=nil
unit4A=nil
//循环强引用会一直阻止myPerson和Apartment类实例的销毁,这就在你的应用程序中造成了内存泄漏
//解决实例之间的循环强引用
//swift提供了两种方法来解决使用类的属性时所遇到的循环强引用问题:弱引用和无主引用
//弱引用和无主引用允许循环引用中的一个实例引用另一个实例而不保持强引用。
//对于生命周期中会变为nil的实例使用弱引用。相反的,对于初始化赋值后再也不会被赋值为nil的实例,使用无主引用。
//因为弱引用可以没有值,你必须将一个弱引用声明为可选类型
john2=myPerson2(name: "hello")
unit4A2=Apartment2(unit: "AAA")
john2!.apartment2=unit4A2
unit4A2!.tenant=john2
john2=nil //myPerson2 hello is being deinit
//由于再也没有指向myPerson2实例的强引用,该实例会被销毁
unit4A2=nil //Apartment2 AAA is being deinit
//由于再也没有指向Apartment2实例的强引用,该实例也会被销毁
//无主引用
//和弱引用类似,无主引用不会牢牢保持住引用的实例。和弱引用不同的是,无主引用是永远有值的。因此,无主引用总是被定义为非可选类型。在声明属性或变量时,在前面加上关键字unowned表示这是一个无主引用
//注意:如果你视图在实例被销毁后,访问该实例的无主引用,会触发运行时错误。使用无主引用,必须确保引用始终指向一个未销毁的实例。
Dlg=Customer(name: "小杜")
Dlg!.card=CreditCard(number: 1234_5678_9999_8888, customer: Dlg!)
//Customer实例持有对CreditCard实例的强引用,而CreditCard实例持有对Customer实例的无主引用
Dlg=nil//小杜 is being deinit
//Card 1234567899998888 is being deinit
//由于再也没有指向Customer实例的强引用,该实例被销毁了,然后,再也没有指向CreditCard实例的强引用,该实例也随之被销毁
myCountry = Country(name: "china", capitalName: "beijing")
print("\(myCountry.name)'s capital city is \(myCountry.capitalCity.name)")//china's capital city is beijing
myCountry=nil //Country is deinit
//City is deinit!
}
}
var myCountry:Country!
class Country {
let name:String
var capitalCity:City!
init(name:String,capitalName:String){
self.name=name
self.capitalCity=City(name: capitalName, country: self)
}
deinit{
print("Country is deinit")
}
}//由于capitalCity默认值为nil,一旦Country的实例在构造函数中给name属性赋值后,整个初始化过程就完成了。这代表一旦name属性被赋值后,Country的构造函数就能引用并传递隐式的self。
class City {
let name:String
unowned let country:Country
init(name:String,country:Country){
self.name=name
self.country=country
}
deinit{
print("City is deinit!")
}
}
var Dlg:Customer?
class Customer {
let name:String
var card:CreditCard?
init(name:String){
self.name=name
}
deinit{
print("\(name) is being deinit")
}
}
class CreditCard {
let number:UInt64
unowned let customer:Customer
init(number:UInt64,customer:Customer){
self.number=number
self.customer=customer
}
deinit{
print("Card \(number) is being deinit")
}
}
var john:myPerson?
var john2:myPerson2?
var unit4A:Apartment?
var unit4A2:Apartment2?
class myPerson2{
let name:String
init(name:String){
self.name=name
}
var apartment2:Apartment2?
deinit{
print("myPerson2 \(name) is being deinit")
}
}
class Apartment2{
let unit:String
init(unit:String){
self.unit=unit
}
weak var tenant:myPerson2?
deinit{
print("Apartment2 \(unit) is being deinit")
}
}
class myPerson{
let name:String
init(name:String){
self.name=name
}
var apartment:Apartment?
deinit{
print("myPerson \(name) is being deinit")
}
}
class Apartment{
let unit:String
init(unit:String){
self.unit=unit
}
var tenant:myPerson?
deinit{
print("Apartment \(unit) is being deinit")
}
}