私は逆アセンブルを確認していませんが、少し異なるソリューションを使用しています。CATiledLayer.content
プロパティをブロックに設定し、nil
キューに入れられたすべてのレンダー ブロックを強制的に完了させます。これは安全にバックグラウンド スレッドにUIView
キックオフできます。その後、解放するとメイン スレッドにキックバックして、ビューとレイヤーのロックを解除できます。
メイン スレッドをブロックすることなく、レンダリングを安全に停止するのに十分な時間、所有しているビューUIViewController dealloc
を維持する実装の例を次に示します。CATiledLayer
- (void)dealloc
{
// This works around a bug where the CATiledLayer background drawing
// delegate may still have dispatched blocks awaiting rendering after
// the view hierarchy is dead, causing a message to a zombie object.
// We'll hold on to tiledView, flush the dispatch queue,
// then let go of fastViewer.
MyTiledView *tiledView = self.tiledView;
if(tiledView) {
dispatch_background(^{
// This blocks while CATiledLayer flushes out its queued render blocks.
tiledView.layer.contents = nil;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// Make sure tiledView survives until now.
tiledView.layer.delegate = nil;
});
});
}
}
これは推測ですが、一部の Apple のフレームワーク/クラス (StoreKit、CATiledLayer、UIGestureRecognizer) は@property (weak) id delegate
実装があると主張していますが、デリゲートを適切に処理していませんweak
。いくつかの逆アセンブルを見ると、彼らは明らかに人種に縛られif != nil
たチェックを行ってから、弱いプロパティに直接触れています。適切な方法は、 a を宣言すること__strong Type *delegate = self.delegate
です。これは成功し、存続が保証された強力な参照を与えるか、または になりますnil
が、ゾンビ オブジェクトへの参照を与えることはありません (私の推測では、フレームワーク コードはアップグレードされていません) 。 ARCへ)。
内部CATiledLayer
的には、バックグラウンド レンダリングを行うディスパッチ キューを作成し、安全でない方法でデリゲート プロパティに触れているように見えるか、ローカル参照を取得しても強力なものにはしていないように見えます。いずれにせよ、デリゲートの割り当てが解除された場合、ディスパッチされたレンダー ブロックはゾンビ オブジェクトに喜んでメッセージを送信します。デリゲートをクリアするだけでは不十分です。クラッシュの数は減りますが、安全に排除することはできません。
を設定するcontent = nil
と、dispatch_wait が実行され、既存のキューに入れられたすべてのレンダー ブロックが完了するまでブロックされます。が安全であることを確認するために、メイン スレッドに戻りdealloc
ます。
誰かが改善のための提案を持っているなら、私に知らせてください。