ARCとは
Swiftは、クラスのメモリ管理にARC(Automatic Reference Counting)という方式を採用しています。
ARCでは、クラスのインスタンスを生成するたびにそのインスタンスのためのメモリ領域を自動的に確保し、不要になったタイミングでそれらを自動的に解放します。
ARCでは使用中のインスタンスのメモリが解放されてしまうことを防ぐために、プロパティ、変数、定数からそれぞれのクラスのインスタンスへの参照がいくつあるかをカウントしています。このカウントが0になったとき、そのインスタンスはどこからも参照されていないとみなされ、メモリが解放されます。このカウントのことを参照カウントと呼びます。
参照カウント
参照カウントは以下のように定義されています。
- インスタンスごとに割り振られる値
- インスタンスを強参照しているプロパティ、定数、変数の個数
ARCの挙動
①新しいインスタンスを作るとARCがメモリ領域を確保し、メモリは以下を保持します。
- インスタンスの型
- ストアドプロパティ
②インスタンスの参照カウントが0になったら、そのインスタンスを記録しているメモリ領域を開放する。
③開放したメモリ領域は、他の目的に使用することができる。
class Sam {
let val: String
init(_ val: String) {
self.val = val
print("\(self.val) メモリ確保維持")
}
deinit {
print("\(self.val) is メモリ解放")
}
}
//Samクラスのインスタンス「インスタンス1」を変数aへ格納
//変数aが「インスタンス1」への参照を持つ
//「インスタンス1」の参照カウントが1になる
var a:Sam? = Sam("インスタンス1") //出力: インスタンス1 メモリ確保維持
//クラスは参照型なので変数bは「インスタンス1」への参照を持つ
//「インスタンス1」の参照カウントが2になる
var b:Sam? = a
//「インスタンス1」の参照カウントが3になる
var c:Sam? = a
//変数aからの参照は無くなるので参照カウントが2(変数bと変数cの参照)になる
a = nil
//変数bからの参照は無くなるので参照カウントが1(変数cの参照のみ)になる
b = nil
//変数cが別の「インスタンス2」を参照したので、
//「インスタンス1」の参照カウントが0になる
c = Sam("インスタンス2") //出力:インスタンス2 メモリ確保維持 出力:インスタンス1 is メモリ解放
do{
//変数dの「インスタンス3」への参照はdoのスコープ内でのみ有効
let d = Sam("インスタンス3") //出力:インスタンス3 メモリ確保維持
}
//この時点で 出力:インスタンス3 is メモリ解放