非常に一般的な状況を一般的な形に蒸留します。オフになり、非同期作業を実行し、完了したらデリゲートメソッドを呼び出すライブラリオブジェクトを構築しているとします。さて、なんらかの理由で、コールバックにARCまたはブロックを使用できないとも言います。昔ながらです。このオブジェクトをワーカーと呼びましょう。
ここで、さまざまなアプリに、パブリックインターフェイス以外にWorkerについて何も知らないクラスがいくつかあるとします。彼らは労働者を自分たちの目的のために使います。これらのクラスをコンシューマーと呼びましょう。
ワーカーが次のようにデリゲートコールバックを作成するとします。
// "Private" method called internally when work is done.
- (void)somethingFinished
{
[self.delegate workerDidFinish];
[self someTask];
}
そして、特定のコンシューマーが次のようにコールバックを処理するとします。
- (void)workerDidFinish
{
// Assume "worker" is a retain property to a Worker
// instance that we previously created and began working,
// and that it's also the sender of the message.
self.worker = nil;
// Other code...
}
現在、その特定のワーカーインスタンスを保持しているものが他にない場合は、問題が発生しています。ワーカーの割り当てが解除された後、制御はその-somethingFinished
メソッドに戻り、そこで-someTask
再利用されたメモリまたはガベージメモリに送信され、クラッシュする可能性があります。メモリ管理ルールに露骨に違反した人は誰もいません。
ここでは技術的な解決策を求めているのではありません。私はいくつかのオプションを知っています。修正の責任は誰にあるのだろうか。コンポーネント設計者として、-somethingFinished
ワーカーの寿命がメソッドの期間中、最初のようなもので延長されるように、ワーカーのメソッドを実装する必要が[[self retain] autorelease]
ありますか?または、コンポーネントのコンシューマーとして、インスタンスメソッドの途中でオブジェクトを吹き飛ばしている可能性があることを認識し、後でリリースするまで待つ必要がありますか?
この質問の回答はすべて、コールバックからオブジェクトを解放することは悪い考えであることを示しているようです。残念ながら、この質問には、ここで意図的に回避したワーカー(この場合はCLLocationManager)がデリゲートにどのように正確に渡されるかについて多くの気が散る情報があります。この質問は同じシナリオに苦しんでおり、他の解決策を提供します。
個人的には、消費者がどのように責任を問われるのかわかりません。これはメモリ管理ルールに違反しておらず、ワーカーのパブリックインターフェイスを丁寧に消費しています。不要になったインスタンスを解放するだけです。しかし一方で、それは、メソッドの途中で割り当てが解除される可能性のあるオブジェクトは、それ自体の寿命を人為的に延長する必要があることを意味しますか?結局のところ、デリゲートメソッドは、メッセージ送信者がメソッドの途中で割り当てを解除する唯一の方法ではありません。
それで、最終的に、誰が修正の責任を負いますか?ワーカー?消費者?正規に決定できますか?