Swift学习之自动引用计数

引用计数

class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("Person:\(name) is being initialized")
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

var reference1:Person?
var reference2:Person?
var reference3:Person?

reference1 = Person(name: "iyaqi") //此时会打印:Person:iyaqi is being initialized
reference2 = reference1
reference3 = reference2

reference3 = nil
reference2 = nil
reference1 = nil // iyaqi is being deinitialized 在这才回销毁,因为有三个指针指向这块内存地址。arc 会再没有强指向的时候销毁该对象,收回地址

1.循环强引用

class Customer {
    let name : String
    init(name:String){self.name = name}
    var apartment:Apartment?
    deinit{
        print("\(name)is being deinited")
    }
}
class Apartment {
    let unit :String
    init(unit:String){self.unit = unit}
    weak var customer:Customer? // 加个weak 相当于apartment 的customer对象是弱引用,这样就不会引起强引用
    deinit{print("Apartment \(unit) is being deinited")}
}

var customer:Customer?
var apartment:Apartment?
customer = Customer.init(name: "iyaiq")
apartment = Apartment(unit: "19900619")
customer!.apartment = apartment
apartment!.customer = customer

//这两个操作不会触发任何deinit动作,因为相互引用,不会释放 加个weak ,就能解决这个问题
customer = nil
apartment = nil

//无主引用
class People{
    let name:String
    var card:CreditCard?
    init(name:String){
        self.name = name
    }
    deinit{print("name:\(name) is deinit")}
}
class CreditCard {
    let number:Int64
    unowned let people:People
    init(number:Int64,people:People){
        self.number = number
        self.people = people
    }
    deinit{print("CreditCard \(number) id deinit")}
}

var people :People?
people = People(name: "iyaqi")
let card = CreditCard(number: 1990, people: people!)
people!.card = card

people = nil //当people销毁的时候,这两个对象都会被销毁 Apartment 19900619 is being deinited,iyaqi is being deinitialized

2.无主引用和隐式解析

class Country {
    let name:String
    var city:City!
    init(name:String,city:String){
        self.name = name
        self.city = City(name:city, country: self)
    }
    deinit{print("Country:\(name) is deinit")}
}

class City {
    let name:String
    unowned var country:Country
    init(name:String,country:Country){
        self.name = name
        self.country = country
    }
    deinit{print("city:\(name) is deinit")}
}

var country:Country? = Country(name: "China", city: "beijing")
var city:City? = City(name: "beijing", country:country!)

print("\(city!.name)") //beijing

city = nil //city:beijing is deinit
country = nil //Country:China is deinit

3.闭包引起的循环强引用

class HtmlElement {
    let name:String
    let text:String?
    lazy var asHTML:Void -> String = {
        [unowned self] in
        if let text = self.text{
            return "<\(self.name)>\(text)"
        }else{
            return "<\(self.name)/>"
        }
    }
    init(name:String,text:String? = nil){
        self.name = name
        self.text = text
    }

    deinit{
        print("htmlElement is deinited")
    }
}

var htmlElement:HtmlElement? = HtmlElement(name:"p")
let defaultText = "some default text"
htmlElement!.asHTML = {
    return "<\(htmlElement!.name)>\(htmlElement!.text ?? defaultText)"
}
print(htmlElement!.asHTML()) // 

some default text

htmlElement = nil//htmlElement is deinited 此时会触发deinit,因为在闭包没有使用self var testHtmlElement:HtmlElement? = HtmlElement(name:"p",text:"hello world") print(testHtmlElement!.asHTML()) //

hello world

testHtmlElement = nil //此时并不会触发deinit,因为在闭包中使用了self

解决在闭包中引用了当前实例的方法

1.定义捕获列表:捕获列表和关键字in放在闭包最开始
2.弱引用和无主引用。
2.1在闭包和捕获的实例总是互相引用并且总是同时销毁时,将闭包内的捕获定义为无主引用
2.2在被捕获的引用可能会变为nil时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil

class TestProtocol{

}

class TestClass {
    var delegate:TestProtocol?
    lazy var someClosure: Void -> String = {
        //在这里,代理可能为空,用弱引用。self跟闭包总是同时销毁,用无主引用。
        [unowned self, weak delegate = self.delegate!] in
        // 这里是闭包的函数体
        return "\(self)'s delegate is : \(self.delegate!)"
    }

    init(delegate:TestProtocol?){
        self.delegate = delegate
    }
}

let testProtocol = TestProtocol()
var testClass = TestClass(delegate: testProtocol)
print(testClass.someClosure()) //TestClass's delegate is : TestProtocol

你可能感兴趣的:(Swift,学习记录)