2019/12/17 Swift 自動参照カウント(Automatic Reference Counting)

Swiftはメモリ管理のために自動参照カウント(Automatic Reference Counting)を使用している。そのためほとんどのケースで、私たちが自分でメモリ管理について考える必要はない。クラスインスタンスがもう必要ない状況になるとARCがそのクラスインスタンスに使われているメモリを解放する。

 

しかしわずかなケースでARCは、メモリ管理のためにコードの中のパーツの関係性に関する情報を必要とする場合がある。この章ではそのようなシチュエーションについて触れ、全てのアプリのメモリ管理のやり方について説明する。

 

参照カウントはクラスインスタンスに関してのみ適用される。構造体や列挙型は値型であり参照型ではないので、参照によって代入や参照渡しが行われるわけではない。

ARCはどのように機能するのか

クラスインスタンスを生成した時は常に、インスタンスに関する情報を格納するためにARCがメモリのチャンクを割り当てます。このメモリは「インスタンスの型」の情報と、「そのインスタンスのストアドプロパティの値」に関する情報を保持する。

加えて、インスタンスが不要になった時、メモリを他の目的で使用できるように、それまでクラスインスタンスに使われていたメモリを解放する。これによりインスタンスが不要になった後もメモリが確保され続けるという状況が起こらないことが保証される。

不要になったインスタンスを割り当て解除(削除)するのは何の問題もないが、もしまだ使う可能性があるインスタンスをARCがメモリから削除してしまうと、そのインスタンスのプロパティやメソッドにアクセスすることができなくなってしまう。実際削除されたインスタンスにアクセスしようとするとアプリがクラッシュする可能性が高い。

インスタンスがまだ必要なのに削除される、ということがないように、ARCは、何個の「変数・定数・プロパティ」がそのインスタンスを参照しているかを数えている。少なくとも一つ以上有効な参照が存在するうちは、ARCがそのインスタンスを削除することはない。

これを可能にするために、クラスインスタンスを「プロパティ・定数・変数」に代入する時は、その「プロパティ・定数・変数」はクラスインスタンスに対する強い参照(強参照)を作成する。この参照はインスタンスに対して強固なホールド(保持)をキープするので「強参照」と呼ばれ、強参照があるうちはインスタンスが削除されることはない。

ARCの挙動

ここにARCの挙動のサンプルを示す。定数のストアドプロパティnameを持つシンプルなクラスPersonを定義する。

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