最終更新: bokkuri_orz 2014年09月22日(月) 01:18:21履歴
Cocoa環境のObjective-Cで用意されているメモリ管理方式。
- リファレンスカウンタ
- ARC(Automatic Reference Counting)
- ガーベジコレクション (Objective-C 2.0 移行。iOSでは使えない)
(1)オブジェクトA が alloc + init でインスタンス生成(リファレンスカウンタ=1) オブジェクトA → (インスタンス) オブジェクトB (2)オブジェクトBがインスタンスを参照する(リファレンスカウンタ=1) オブジェクトA → (インスタンス) ← オブジェクトB (3)オブジェクト1がインスタンスの参照をやめる(リファレンスカウンタ=0) オブジェクトA (インスタンス) ← オブジェクトB (4)インスタンスが開放されるが、オブジェクトBはインスタンスが存在していたメモリを参照したまま。 オブジェクトA ( ) ← オブジェクトB
(1)オブジェクトA が alloc + init でインスタンス生成(リファレンスカウンタ=1) オブジェクトA → (インスタンス) オブジェクトB (2)オブジェクトBがインスタンスを参照し、retainを呼ぶ(リファレンスカウンタ=2) オブジェクトA → (インスタンス) ← オブジェクトB (3)オブジェクト1がインスタンスの参照をやめる(リファレンスカウンタ=1) オブジェクトA (インスタンス) ← オブジェクトB (4)インスタンスのリファレンスカウンタが残っているので、インスタンスは破棄されずに残っている(ルファレンスカウンタ=1) オブジェクトA (インスタンス) ← オブジェクトB
オブジェクトがインスタンスをalloc+initしたり、retainを送ってカウンタをインクリメントすることで、
そのインスタンスを保持(retain)していることになる。
インスタンスを保持することを、 「オーナーシップを持っている」 という。
// NSObjectを継承する @interface MyObj: NSObject { } // イニシャライザ -(id)new という書き方もある -(id)init; -(void)dealloc; @end @implementation MyObj -(id)init { printf("MyObj init\n"); return self; } -(void)dealloc { printf("MyObj dealloc\n"); [super dealloc]; } @end { MyObj* obj = [[MyObj alloc] init]; printf("retainCount 0 : %d\n", (int)[obj retainCount]); [obj retain]; printf("retainCount 1 : %d\n", (int)[obj retainCount]); [obj release]; printf("retainCount 2 : %d\n", (int)[obj retainCount]); [obj release]; }
●実行結果
MyObj init retainCount 0 : 1 retainCount 1 : 2 retainCount 2 : 1 MyObj dealloc
オーナーシップを持つ場合の注意点について。
-(void)setMyValue:(id)obj { [myValue release]; myValue = [obj retain]; // ← myValue同じインスタンスが渡された場合、上のreleaseで解放されてしまうことがある。 }
●対策
//例1 -(void)setMyValue:(id)obj { [obj retain]; // リファレンスカウンタを先に増やしておく [myValue release]; // 上記対応で、ここで解放されることがなくなる myValue = obj; } //例2 -(void)setMyValue:(id)obj { if(myValue != obj) { [myValue release]; myValue = [obj retain]; } }
NSAutoreleasePool を使うと、後でまとめてインスタンスへreleaseメッセージを送ることが出来る。
前述の MyObj を使った例。
●サンプルコード
{ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // 自動解放プール開始 MyObj* obj = [[MyObj alloc] init]; [obj autorelease]; // 自動解放プールへ登録 [pool drain]; // 自動解放プール終了 }
●実行結果
MyObj init MyObj dealloc
NSString のメソッド
メソッド | 説明 | 所有者 |
-(id) initWithUTF8String | allocで生成したインスタンスに対するイニシャライザ。 | 生成したオブジェクトがインスタンスのオーナー |
+(id) stringWithUTF8String | 一時的なインスタンスを生成するメソッド | オーナー無し。自動解放プールに登録される。 |
●メソッドの命名規則
allocのイニシャライザは init〜
一時的なインスタンスを生成するメソッド、文字列は string〜、配列は array〜 という感じ。
タグ
最新コメント