これは私のパターンです:デリゲートにインスタンスが不要になったことを正しく通知する方法
1)SpecialViewはMessageViewを作成し、それに対する強い参照を保持します。
2)ユーザーがMessageView内のボタンをタップすると、メッセージがフェードアウトします。それから、MessageViewはそれが完全にフェードアウトしたことを、そのデリゲート、SpecialViewに伝えます。
3)SpecialViewがMessageViewをリリースしました。私は順番に、すぐMessageViewを解放デリゲートを呼んでいる最後の行で
- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
[self.delegate messageViewFadedOut:self]; // delegate releases us...
// self maybe got deallocated... BOOM!
// now what? method of a zombie returns? stack freaks out?
} // does it even return?
:
問題は、このです。 -fadedOut:finished:context:コアアニメーションdidStopSelectorコールバックによって呼び出されます。
は私の恐怖はMessageViewインスタンスがすぐに-fadedOut前を割り当て解除しようとしているということです:終了:コンテキスト:非常に厄介なランダムなバグワンス・アポン・ア・タイム
を起こし、完全に返され、古いベテランプログラマは語りました私:あなたが座っている枝を切らないでください。
だからインスタンスは、このメソッドが戻るまで生き残ることを確認するために、私は、デリゲートを呼び出す前に保持-autorleaseダンスをした:
- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
//[[self retain] autorelease];
[self.delegate messageViewFadedOut:self]; // delegate releases us...
}
しかし、ARCの下で、保持-autoreleaseの踊りは許可されませんもはや(移行ツールでは許可されません)、ARCシステムにこのようなことをさせる方法がないようです。
だから私が代わりにこの戦略を思い付いた:遅れperformSelectorがうまくいけば、この方法が完全に戻ることができます
- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
[self.delegate performSelector:@selector(messageViewFadedOut:) withObject:self afterDelay:0];
}
。私が知る限り、0の遅延は、セレクタがすぐにではなく次の実行ループの繰り返しで実行されることを保証します。
これは偽の可能性もあります。
他のオブジェクトを呼び出すメソッドが完全に返される前にオブジェクトが取得されてしまう可能性があるため、別のオブジェクトに最後の参照を破棄するように要求するこの問題を正しく解決するにはどうすればよいですか?スタックトレースゾンビのようなものがありますか?
ARCではどのようにこのような問題を解決する必要がありますか?
しかし、実際の問題は次のようなものです。オブジェクトの割り振り解除が完了する前に、オブジェクトの割り振り解除が発生した場合は危険ですか?上記のコードでわかるように、デリゲートを呼び出した後は何も起こりません。だから理論的には問題はありません。ゾンビが復帰しているという事実について、ランタイム・フリークを除いて。 – openfrog
ああ。いいえ、私が知る限り危険ではありません。私は本番アプリでそれを自分で行い、悪影響はありませんでした。私はメソッドの最後の行でこれを行うしかありませんでした。さもなければ、 'dealloc'd' self'にアクセスしようとする何かがあるかもしれません。 – darvids0n