天天看點

Swift實用小冊23: ARC自動引用計數機制的使用

在本章中,你将學會ARC自動引用計數機制的使用方法。

前言

和​

​Apple​

​​官網或者網上分享的教程類文章不同,我将以實際開發角度講述​

​Swift​

​​語言的一些概念和用法,友善大家更好地學習和掌握​

​Swift​

​語言。

這同時也是對自己學習​

​Swift​

​語言過程的知識整理。

如有錯誤,以你為準。

項目建立

我們建立一個​

​PlayGround​

​​項目,命名為​

​SwiftARC​

​。

Swift實用小冊23: ARC自動引用計數機制的使用

ARC的定義

​ARC​

​,自動引用計數機制,是​

​Swift​

​官方提供的一種跟蹤和管理應用程式的記憶體的機制。

​ARC​

​可以幫助我們設計的應用程式自動釋放記憶體,保證我們執行個體在使用完成後不會占用記憶體資源,保障應用程式運作的流暢性。

ARC的功能

使用​

​init()​

​​方法建立一個類的執行個體時,​

​ARC​

​會配置設定記憶體用來儲存執行個體的資訊,記憶體中會包含執行個體的類型資訊,以及這個執行個體所有相關屬性的值。

當執行個體不再被使用時,​

​ARC​

​​釋放執行個體所占用的記憶體。為了確定使用中的執行個體不會被銷毀,​

​ARC​

​會跟蹤和計算每一個執行個體正在被多少屬性,常量和變量所引用。

執行個體指派給屬性、常量或變量,都會建立執行個體的強引用,隻要強引用還在,執行個體就不會被銷毀。

ARC的使用

我們用之前​

​Destructor​

​​析構函數的例子展示​

​ARC​

​自動引用計數機制的使用。示例:

class appInformation {
    var appName: String
    var appVersion: String
    var appAuthor: String

    // 構造函數
    init(appName: String, appVersion: String, appAuthor: String) {
        self.appName = appName
        self.appVersion = appVersion
        self.appAuthor = appAuthor
        print("調用構造函數")
    }

    // 析構函數
    deinit {
        print("調用析構函數")
    }
}      
Swift實用小冊23: ARC自動引用計數機制的使用

上述代碼中,我們定義了一個​

​appInformation​

​​類,然後聲明了三個​

​String​

​​類型的變量:​

​appName​

​​、​

​appVersion​

​​、​

​appAuthor​

​。

​appInformation​

​​類有一個構造器,構造器給執行個體的變量屬性指派,然後列印一條資訊:​

​調用構造函數​

​。

​appInformation​

​​類有一個析構器,析構器在執行個體被銷毀時列印一條資訊:​

​調用析構函數​

​。

強引用

接下來,我們建立一個執行個體。

var app: appInformation?
app = appInformation(appName: "Swift實用小冊", appVersion: "1.0.0", appAuthor: "文如秋雨”)
app = nil      
Swift實用小冊23: ARC自動引用計數機制的使用

上述代碼中,我們建立了一個​

​appInformation​

​​類的執行個體:​

​app​

​​,并将​

​appInformation​

​​執行個體指派給了​

​app​

​。

這樣在我們調用​

​appInformation​

​​構造器時,會列印輸出一條資訊:​

​調用構造函數​

​。

由于​

​appInformation​

​​執行個體指派給了​

​app​

​​變量,是以​

​app​

​​變量和​

​appInformation​

​​執行個體之間會建立一個​

​強引用​

​。

又由于這個強引用的存在,​

​ARC​

​​自動引用計數機制會保證​

​appInformation​

​執行個體會儲存在記憶體中不會被銷毀。

當我們要斷開強引用時,我們可以通過給​

​app​

​​變量指派​

​nil​

​​,這樣這個強引用就會被斷開,​

​appInformation​

​執行個體也就會被銷毀,進而釋放記憶體。

弱引用

在上面的例子中,​

​ARC​

​​會跟蹤我們建立的​

​appInformation​

​執行個體的引用數量,并且在不需要用到的時候銷毀它。

但如果我們使用2個或以上的類的執行個體,然後它們之間互相建立強引用,這就導緻永遠都不可能釋放這部分的記憶體。

這是一個很嚴重的問題。

是以,我們引用了弱引用的概念。

弱引用能保證我們在多個執行個體循環引用時不保持強引用的狀态。示例:

class Model1 {
    let name: String
    init(name: String) { self.name = name }
    var strongModel: Model2?
    deinit { print("釋放") }
}

class Model2 {
    let title: String
    init(title: String) { self.title = title }
    weak var weakModel: Model1?
    deinit { print("釋放") }
}      
Swift實用小冊23: ARC自動引用計數機制的使用

上述代碼中,我們建立了​

​2​

​​個類:​

​Model1​

​​、​

​Model2​

​,并都對其進行初始化。

然後在​

​Model1​

​類中強引用​

​Model2​

​​類,在​

​Model2​

​類中弱引用​

​Model1​

​​類,然後我們建立兩個變量​

​model1​

​​、​

​model2​

​之間的強引用,并關聯兩個執行個體:

var model1: Model1?
var model2: Model2?

model1 = Model1(name: "文如秋雨")
model2 = Model2(title: "Swift實用小冊”)

model1 = nil      
Swift實用小冊23: ARC自動引用計數機制的使用

如果這時候,我們将​

​model1​

​​的強引用斷開,那麼類​

​Model1​

​​的執行個體就會被銷毀,又由于我們​

​Model2​

​使用弱引用,這時候就不會循環建立兩個類的執行個體的強引用關系,導緻兩個執行個體都占用記憶體。

本章代碼

import UIKit

class appInformation {
    var appName: String
    var appVersion: String
    var appAuthor: String

    // 構造函數
    init(appName: String, appVersion: String, appAuthor: String) {
        self.appName = appName
        self.appVersion = appVersion
        self.appAuthor = appAuthor
        print("調用構造函數")
    }

    // 析構函數
    deinit {
        print("調用析構函數")
    }
}

var app: appInformation?
app = appInformation(appName: "Swift實用小冊", appVersion: "1.0.0", appAuthor: "文如秋雨")
app = nil

class Model1 {
    let name: String
    init(name: String) { self.name = name }
    var strongModel: Model2?
    deinit { print("釋放") }
}

class Model2 {
    let title: String
    init(title: String) { self.title = title }
    weak var weakModel: Model1?
    deinit { print("釋放") }
}

var model1: Model1?
var model2: Model2?

model1 = Model1(name: "文如秋雨")
model2 = Model2(title: "Swift實用小冊")

model1 = nil