そこで、この手法を使用して、オブジェクトが常にバックグラウンドスレッドで割り当て解除されるようにしました。一部のクラスの[dealloc]は適度に重いため、長い時間(数十ミリ秒)かかる可能性があり、メインスレッドがわずかにフリーズしていました。
これらの重いオブジェクトはすべて、メインスレッドで解放される前に配列に追加し、後でバックグラウンドスレッドでその配列を調べて、配列から削除することにしました。配列は、バックグラウンドスレッドで配列から削除できるようになるまで、retainCountを存続させ、メインスレッドで[dealloc]のコストが発生しないことを保証できると考えられていました。
これを行うために、私は以下のコードを持っていました:
while([objectsToDealloc count] && /* other conditions to prevent infinite loop */){
__weak id ref = [objectsToDealloc lastObject];
[objectsToDealloc removeLastObject];
@synchronized(ref){
// synchronising on ref will retain it if possible.
// so if its still around,that means we didn't dealloc it
// like we were asked to.
// so insert it back into our array. once the object is deallocd
// it won't be able to be synchronized, because the weak ref will
// be nil
if(ref){
[objectsToDealloc insertObject:ref atIndex:0];
}
}
}
配列に最後の参照が含まれていなかった場合(またはオブジェクトに保留中の自動解放があった場合など)、弱参照がゼロにならないという考え方でした。次に、オブジェクトで@synchronizeします-同期されたブロックは、同期されているオブジェクトを保持+解放します-これにより、ref
そのブロックの間、が存続することが保証されます。それがゼロだった場合、それは割り当てが解除されていました。nilでない場合は、配列に追加し直して、後でもう一度確認する必要があります。
過去数週間にわたってこのコードでテストした後、割り当て解除されたオブジェクトをチェックするためにこの戦略を推奨することはできません。正確な理由はまだわかりませんが、オブジェクトのロックが解除されることはめったにありませんが、refはまだnilになっていないため、無効なオブジェクトを配列に追加し直します。
デバッガーでこれを1回だけキャッチしましたが、クラッシュログが数回発生しています。上記のコードはそれから保護する必要がありますが、以下で「nil」が私の配列に含まれることがわかります。

繰り返しになりますが、オブジェクトの割り当てが解除されたとき/かどうかを検出するためにこの手法を使用せず、代わりにオブジェクトのグラフと関係を明確にすることに注力することをお勧めします。