Objective-C を始めたのがちょうどARC (Automatic Reference Counting) が登場してからなので、これまでメモリに関する知識がさほどないまま、ARC任せでアプリ開発を行っていました。
ある程度 Objective-C での開発に慣れてくると、中途半端な知識では何かと不都合なことが散見するようになり、このままではいけないと思ったので、ARCに関する知識をまとめることにしました。
【このコンテンツは随時コンテンツを追加・更新していきます】
ARCについて
ARCを使用することでメモリ管理を完全に放棄できるわけではなく、変数のスコープやオブジェクトが破棄されるタイミング、「強い参照」と「弱い参照」といった仕組みの理解は最低限必要です。
ここではARCに関する概要と禁止事項をピックアップしました。
ARCの概要
- メモリ管理の基本的な仕組みはマニュアルでの管理方法と同じで、各オブジェクトが参照カウンタを持ち、カウンタが0になるとオブジェクトが破棄される。
- ARC はコンパイラが適切な場所に retain, release, autorelease, dealloc を挿入してくれる機能。
- 強い参照がある間はそのオブジェクトは破棄されない。
- 弱い参照自が存在しても、強い参照がなくなればそのオブジェクトは破棄される。
禁止事項
- retain, release, autorelease,dealloc, [super dealloc] は ARC が自動で挿入してくれるため使用してはならない。
- @selector(retain) や @selector(release) でのセレクタ呼び出しをしてはいけない。
- @property 宣言に assign/retain/copy パラメータは不要。
- NSAutoReleasePool の代わりに @autoreleasepool を使う。
補足事項
- プロパティで weak を指定すれば、Outlet に nil を入れる必要はない。
[code]@property (weak) IBOutlet UILabel *XXX;[/code]
- iOS 6 以降はメモリ不足時に viewDidUnload が呼ばれないため、メモリ使用量が多いオブジェクトは didReceiveMemoryWarning で解放する。
- 明示的にビューを解放したいときは didReceiveMemoryWarning で以下のようなコードを実行する。
[code]
– (void)didReceiveMemoryWarning {
if([self isViewLoaded] && [self.view window] == nil) {
[XXX removeAllObjects];
self.view = nil;
self.XXXImageView = nil;
}
}
[/code]
強い参照と弱い参照について
ARC が実装されてからは __strong や __weak といった修飾子が追加されました。それぞれ強い参照、弱い参照を定義するために使用します。修飾子を省略した場合は強い参照のオブジェクトとなります。
強い参照
- 修飾子の使用例
[code]__strong MyClass *obj = [[MyClass alloc] init];[/code]
- プロパティの使用例
[code]_@property(strong) NSObject *obj;[/code]
- 何も指定がない場合(デフォルト)は強い参照となる
- 参照先のオブジェクトを自分で保持する。参照されなくなったり、スコープ外に出た場合は破棄される。
- alloc/init で生成されたオブジェクトは、現在のスコープのライフタイムの間維持される。
弱い参照
- 修飾子の使用例
[code]__weak MyClass *wobj = obj;[/code]
- プロパティの使用例
[code]_@property(weak) NSObject *obj;[/code]
- 弱い参照も別の場所では強参照されている必要がある。
- __weakが指定されたオブジェクトは、いつでも削除される可能性がある。
- 参照先のオブジェクトを自分で保持しない。参照されなくなったとき自動的に nil が代入される。
- オブジェクトが破棄された場合、この弱い参照にはnilが設定される。
- デリゲートパターンの使用時に相互循環を防止するために使用する。
まとめ
弱い参照も別の場所では強参照されている必要があります。
強い参照により任意の1ヶ所でそのオブジェクトを所有し、他の場所では弱い参照を持ちそのオブジェクトにアクセスする、というのが弱い参照の基本的な使い方です。