0

シングルビューアプリが作成された場合、FooViewそのサブクラスを使用UIViewして、

NSLog(@"hello");

drawRect、それからそれは印刷されます。

CALayerそして、呼び出されたのサブクラスを作成し、CoolLayerこのメソッドをFooView.m:に追加するとします。

+(Class) layerClass {
    return [CoolLayer class];
}

FooView.mそして、の終わりにdrawRect

NSLog(@"layer's class is %@", self.layer.class);

その後CoolLayer、印刷されます。つまり、ビューの下にあるレイヤーはCoolLayerです。

しかし、以下が追加された場合CoolLayer.m

-(void) display {

}

これは、レイヤーを再描画するために自動的に呼び出されるメソッドであり(と同様drawRect)、NSLog印刷されません。アプリが無限ループに入った可能性があります。(touchesBeganNSLogメッセージを出力する私のものでさえ印刷されていません)。ブレークポイントがに設定されている場合、ブレークポイントはdisplayそこで一度停止しますが、プログラムを続行すると、ブレークポイントは二度と到達しませんdisplay。これの何が問題になっていて、どうすれば修正できますか?

4

3 に答える 3

2

レイヤーの表示メソッドは、レイヤーが汚れていない限り、つまり再表示が必要に設定されていない限り、再度呼び出されることはありません。これは通常は良いことであり、メソッドが複数回呼び出されることがないのはそのためです。

また、display の通常の実装はdrawInContext:メソッドを呼び出します。サブクラスでこれをオーバーライドするためdrawRect:、ビューのメソッドが呼び出されることはありません。の標準動作を複製するか、独自の実装でスーパークラスのメソッドをCALayer呼び出す必要があります。display

于 2012-05-28T15:36:16.377 に答える
2

それは無限ループのようには聞こえません。無限ループに陥った場合、アプリはフリーズし、数秒後にスプリングボード アプリは応答しないためにアプリを強制終了します。

レイヤーで setNeedsDisplay または setNeedsDisplayInRect を呼び出して、レイヤーを「ダーティ」にし、再度描画する必要があります。必要以上に setNeedsDisplay を呼び出したくないことに注意してください。レイヤーを再レンダリングしてその内容を画面にプッシュするには多くの作業が必要になるためです。何かが変更された場合にのみ表示

于 2012-05-28T15:14:37.413 に答える
1

ここでは無限ループは見られません。ダンカンが指摘しているように、ウォッチドッグタイマーが原因で、またはデバッガーに表示されるスタックトレースですぐにわかる無限再帰が原因で、最終的にクラッシュする可能性があります。

NSLogをUIViewの-drawRect:メソッドに配置し、デフォルトのレイヤークラスを、独自の描画を行う独自のカスタムCALayerでオーバーライドすると、UIView-drawRect:は呼び出されなくなります。これで、描画はカスタムバッキングレイヤーによって処理されます。

Core Animationプログラミングガイドの「サブクラス化によるCALayerコンテンツの提供」サブセクションで説明されているように、レイヤーのCGImageRef-displayを何らかの方法でカスタマイズする場合は、通常、CALayerでオーバーライドします。通常、 CALayer内でカスタムQuartz描画をレンダリングする場合contentsは、オーバーライドします。-drawInContext:オーバーライドさ-displayれたメソッドを完全に空白にし、contentsプロパティに何も書き込まないようにすることは標準的な動作ではないため、これを行うと奇妙な結果が表示されるのは驚きではありません。

最近の一連の質問に基づいて、先に進む前に、Core Animationプログラミングガイドを読み、CALayersに関連するサンプルコードを確認することを強くお勧めします。

于 2012-05-28T22:20:24.957 に答える