retain
とrelease
;から始めましょう。autorelease
基本的な概念を理解すれば、実際には特殊なケースにすぎません。
Cocoa では、各オブジェクトが参照された回数を追跡します (具体的には、NSObject
基本クラスがこれを実装します)。オブジェクトを呼び出すことretain
で、参照カウントを 1 つ増やしたいことをオブジェクトに伝えます。を呼び出すことrelease
で、オブジェクトを手放すことを伝え、その参照カウントを減らします。を呼び出した後release
、参照カウントがゼロになった場合、そのオブジェクトのメモリはシステムによって解放されます。
これが異なる基本的な方法malloc
はfree
、オブジェクトが使用していたメモリを解放したため、特定のオブジェクトがシステムの他の部分がクラッシュすることを心配する必要がないことです。誰もがルールに従ってプレイし、保持/解放していると仮定すると、1 つのコードがオブジェクトを保持してから解放しても、そのオブジェクトを参照している他のコードは影響を受けません。
retain
混乱を招くことがあるのは、とを呼び出す必要がある状況を知ることですrelease
。私の一般的な経験則は、あるオブジェクトをしばらく保持したい場合 (たとえば、それがクラスのメンバー変数である場合)、オブジェクトの参照カウントが私について知っていることを確認する必要があるということです。前述のように、オブジェクトの参照カウントは を呼び出すことでインクリメントされますretain
。慣例により、オブジェクトが「init」メソッドで作成されたときにもインクリメントされます (実際には 1 に設定されます)。どちらの場合でもrelease
、オブジェクトを使い終わったときにオブジェクトを呼び出すのは私の責任です。そうしないと、メモリリークが発生します。
オブジェクト作成の例:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
今すぐautorelease
。Autorelease は、しばらくしてからこのオブジェクトを解放するようにシステムに指示する便利な (そして場合によっては必要な) 方法として使用されます。配管の観点からは、autorelease
が呼び出されると、現在のスレッドNSAutoreleasePool
に呼び出しが通知されます。は、(イベント ループのNSAutoreleasePool
現在の繰り返しの後) 機会が得られるとrelease
、オブジェクトを呼び出すことができることを認識しています。プログラマーとしての私たちの観点からは、呼び出しrelease
を処理してくれるので、呼び出す必要はありません (実際、そうすべきではありません)。
注意すべき重要な点は、(繰り返しますが、慣例により) すべてのオブジェクト作成クラスメソッドは、自動解放されたオブジェクトを返すということです。たとえば、次の例では、変数 "s" は参照カウントが 1 ですが、イベント ループが完了すると破棄されます。
NSString* s = [NSString stringWithString:@"Hello World"];
その文字列に固執したい場合は、明示的に呼び出し、完了したらretain
明示的に呼び出す必要がありrelease
ます。
次の (非常に不自然な) コードのビットを検討すると、autorelease
必要な状況が表示されます。
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
私はこれがすべて少し混乱していることに気付きました - しかし、ある時点で、それはクリックします. ここにあなたが始めるためのいくつかの参考文献があります: