在本章中,你将學會ARC自動引用計數機制的使用方法。
前言
和
Apple
官網或者網上分享的教程類文章不同,我将以實際開發角度講述
Swift
語言的一些概念和用法,友善大家更好地學習和掌握
Swift
語言。
這同時也是對自己學習
Swift
語言過程的知識整理。
如有錯誤,以你為準。
項目建立
我們建立一個
PlayGround
項目,命名為
SwiftARC
。
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("調用析構函數")
}
}
上述代碼中,我們定義了一個
appInformation
類,然後聲明了三個
String
類型的變量:
appName
、
appVersion
、
appAuthor
。
appInformation
類有一個構造器,構造器給執行個體的變量屬性指派,然後列印一條資訊:
調用構造函數
。
appInformation
類有一個析構器,析構器在執行個體被銷毀時列印一條資訊:
調用析構函數
。
強引用
接下來,我們建立一個執行個體。
var app: appInformation?
app = appInformation(appName: "Swift實用小冊", appVersion: "1.0.0", appAuthor: "文如秋雨”)
app = nil
上述代碼中,我們建立了一個
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("釋放") }
}
上述代碼中,我們建立了
2
個類:
Model1
、
Model2
,并都對其進行初始化。
然後在
Model1
類中強引用
Model2
類,在
Model2
類中弱引用
Model1
類,然後我們建立兩個變量
model1
、
model2
之間的強引用,并關聯兩個執行個體:
var model1: Model1?
var model2: Model2?
model1 = Model1(name: "文如秋雨")
model2 = Model2(title: "Swift實用小冊”)
model1 = nil
如果這時候,我們将
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