2012年2月
« 1月   3月 »
 12345
6789101112
13141516171819
20212223242526
272829  
2012/02/25

iOS5時代のメモリ管理 その3 ARCの記述

メモリ管理の概要ARCの設定に続いて、ARC(Automatic Reference Counting)対応のソースの記述についてです。

メモリの領域を参照数をカウントして、ゼロになった場合に解放するという考え方は同じですが、ARCによって記述が簡単になります。

今まで明示的にretainやreleaseを記述していましたが、以下の記述は全てエラーになります。

・retain
・release
・retainCount
・autorelease

代わりにポインタを管理する変数の修飾子が増えてます。

・__strong
・__weak
・__unsafe_unretained
・__autoreleasing

例えば、以下のような記述をします。

SomeObject * __strong obj;

以下のようにこの変数にポインタを代入した場合、

obj = someObj;

以下と同じ意味で、オブジェクトを所有した事になります。(retainカウントが1増える)

obj = someObj;

[obj retain];

修飾子を省略した場合は「__strong」の扱いなので、実質記述を省略する事ができて、且つ、releaseについては、nilを入れたり、変数がスコープから抜けた際に自動で行われるので、かなりソースがすっきりします。

※メソッドの戻り値の扱いが曖昧ですが、「alloc」「new」「copy」「mutableCopy」で始まる名前のメソッドはretainカウントが1の状態で返して、それ以外のメソッドに関してはautoreleaseしてから返すようです。

 

それぞれの修飾子の意味は以下の通りです。

 

■__strong

オブジェクトを所有する(retainする)強い参照。

 

■__weak

オブジェクトを所有しない(retainカウントを変更しない)弱い参照。
参照しているオブジェクトが解放された場合は自動でnilが入る。

オブジェクトで相互にポインタを保持したい場合など、__strongで保持すると参照が循環してしまって、解放されない状態になるのを回避したい時に使う。

delegate先のオブジェクトの管理に使うのがイメージしやすいと思います。

 

■__unsafe_unretained

iOS5以前のOSでは__weakが使えないので、古いOSに対応する場合は__unsafe_unretainedを使う。(__weakはコンパイラだけで実現されているのではなく、OSの機能も関係がある。)

参照先のオブジェクトが解放されてもnilが入らないので、参照先のオブジェクトの状態に注意する必要がある。

 

■__autoreleasing

autoreleaseを呼び出したときと同じ扱い。

 

 

autoreleaseに関しては、NSAutoreleasePoolも使えなくなっています。

代わりに以下のブロックを記述できるようになっています。

@autoreleasepool
{
}

ブロックの開始時にpoolが作られて、ブロック終了時にpoolが解放されます。

つまりブロック内でautoreleasepoolに追加されたオブジェクトは、ブロックを出た際にreleaseされることになります。

__strongで定義された変数で管理されているオブジェクトも変数のスコープを出るとreleaseされるので、以下のような記述をした場合はautoreleasepoolのブロックを出た際にリリースされます。

@autoreleasepool
{
 NSMutableArray *someObj = [NSMutableArray arrayWithCapacity:1];
}

※arrayWithCapacityはautorelease状態のオブジェクトを返して、__strongのsomeObjに代入されるが、ブロックを出たタイミングでsomeObjのスコープが外れ、且つautoreleasepoolが解放されるので、オブジェクトは解放される。

@autoreleasepoolのブロックは入れ子構造にもできます。

@autoreleasepoolブロックについては、ARCが無効でも、LLVMコンパイラ3.0以降を使っていれば使えます。

 

 

ARCのもう一つの大きな違いは、deallocを明示的に呼び出せないという所です。

NSObjectを継承して独自のオブジェクトを作った場合、以下のような記述を行っていました。

-(void)dealloc
{
 [super dealloc];
}

この中の[super dealloc];がエラーになります。

ARCでは親クラスのdeallocが呼ばれてからdeallocが呼ばれるので、子クラス側で使っているオブジェクトの後処理だけ書けばOKです。

インスタンス変数にnilを入れて参照を無くすような処理が考えられます。

 

 

Objective-CはTool-free bridgeと呼ばれる仕組みで、C言語と共存できるのが特徴ですが、ARCはObjective-Cで使えるものなので、C言語が混ざって来たときは別の記述が必要になってきます。

次回はC言語で書かれたCoreFoundationを使う場合の記述について書きたいと思います。


※iPhoneアプリ開発に関する投稿を今から始めるiPhoneアプリ開発にまとめました。

Comments are closed.