4

今日、CATiledLayer に関する興味深い iOS の問題に遭遇しました。これはデバイス上でのみ発生し、シミュレーターでは発生しませんでした。

私のビューは、drawLayer: inContext: デリゲート コールバックを介してその CALayer を描画します。このレイヤーには CATiledLayer から派生したサブレイヤーがあり、オーバーライドされた drawInContext: メソッドで独自の描画を行います。

どちらのレイヤーも、CGContextDrawPDFPage() を介して pdf コンテンツをレンダリングしています。(CALayer は低解像度バージョンを描画し、CATiledLayer サブレイヤーはその上に高解像度コンテンツを描画します。)

私はビューを使い果たし、スーパービューからビューを削除して解放するというシナリオに遭遇しました。ビューで dealloc() が呼び出されます。しばらくして、CATiledLayer の drawInContext: メソッドがシステムによって (バックグラウンド スレッドで) 呼び出されます。それは描画しますが、Springboard メソッドから戻るとクラッシュし、その際にアプリもダウンします。

ビューの dealloc メソッドから、CATiledLayer にフラグを設定して、これ以上レンダリングしないように指示することで修正しました。

しかし、もっとエレガントな方法があるとしか想像できません。CATiledLayer drawInContext: メソッドがまだ親レイヤーの後に呼び出され、親レイヤーのビューの割り当てが解除されたのはなぜですか? これが起こらないようにビューをシャットダウンする正しい方法は何ですか?

4

4 に答える 4

10

時間はかかりますが、修正する最善の方法は、 も設定することview.layer.contents = nilです。これは、スレッドが終了するのを待ちます。

于 2011-08-12T09:30:01.073 に答える
3

view.layer.delegateビューを解放する前にnilに設定してください。

于 2011-02-09T09:53:12.090 に答える
0

これにかなりの時間を費やしました。私の最新のアプローチは、ブロック変数を宣言し、viewWillDisappear メソッドで自分自身に割り当てることです。次に、グローバル ディスパッチ キューに対して setContents 呼び出しを呼び出します。メイン スレッドをロックする必要はありません。次に、setContents が呼び出されてメイン スレッドに戻り、ブロック変数を nil に設定します。これにより、View Controller がメイン スレッドで確実に解放されます。ただし、1 つの注意点として、グローバル ディスパッチ キューがブロックを終了するまでビュー コントローラーを保持するため、メイン スレッドへの呼び出しに dispatch_after を使用するのが賢明であることがわかりました。ビュー コントローラ) およびブロック変数を nil に設定するメイン スレッド ブロック) により、グローバル ディスパッチ キュー スレッドで割り当てが解除される可能性があります。

于 2013-05-10T11:48:43.353 に答える
0
-(void)drawLayer:(CALayer *)calayer inContext:(CGContextRef)context {    
   if(!self.superview)
      return;
   ...

更新: 私が思い出したように、CATiledLayers に関しては古いバージョンの iOS でこれに問題がありましたが、dealloc の前にデリゲートを nil に設定することが現在の方法です。参照: https://stackoverflow.com/a/4943231/2882

于 2011-03-31T15:29:41.617 に答える