ビューを強制的に同期的に描画する (呼び出し元のコードに戻る前に)返金が保証された鉄筋コンクリートの確実な方法は、 とサブクラスCALayer
との相互作用を構成することです。UIView
UIView サブクラスでdisplayNow()
、レイヤーに「<em>表示コースを設定」してから「<em>そのようにする」ように指示するメソッドを作成します。
迅速
/// Redraws the view's contents immediately.
/// Serves the same purpose as the display method in GLKView.
public func displayNow()
{
let layer = self.layer
layer.setNeedsDisplay()
layer.displayIfNeeded()
}
Objective-C
/// Redraws the view's contents immediately.
/// Serves the same purpose as the display method in GLKView.
- (void)displayNow
{
CALayer *layer = self.layer;
[layer setNeedsDisplay];
[layer displayIfNeeded];
}
draw(_: CALayer, in: CGContext)
また、プライベート/内部描画メソッドを呼び出すメソッドを実装します(すべてUIView
が a であるため、これは機能しますCALayerDelegate
)。
迅速
/// Called by our CALayer when it wants us to draw
/// (in compliance with the CALayerDelegate protocol).
override func draw(_ layer: CALayer, in context: CGContext)
{
UIGraphicsPushContext(context)
internalDraw(self.bounds)
UIGraphicsPopContext()
}
Objective-C
/// Called by our CALayer when it wants us to draw
/// (in compliance with the CALayerDelegate protocol).
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
UIGraphicsPushContext(context);
[self internalDrawWithRect:self.bounds];
UIGraphicsPopContext();
}
internalDraw(_: CGRect)
そして、fail-safe とともにカスタム メソッドを作成しますdraw(_: CGRect)
。
迅速
/// Internal drawing method; naming's up to you.
func internalDraw(_ rect: CGRect)
{
// @FILLIN: Custom drawing code goes here.
// (Use `UIGraphicsGetCurrentContext()` where necessary.)
}
/// For compatibility, if something besides our display method asks for draw.
override func draw(_ rect: CGRect) {
internalDraw(rect)
}
Objective-C
/// Internal drawing method; naming's up to you.
- (void)internalDrawWithRect:(CGRect)rect
{
// @FILLIN: Custom drawing code goes here.
// (Use `UIGraphicsGetCurrentContext()` where necessary.)
}
/// For compatibility, if something besides our display method asks for draw.
- (void)drawRect:(CGRect)rect {
[self internalDrawWithRect:rect];
}
そしてmyView.displayNow()
、描画するために本当に本当に必要なときはいつでも呼び出すだけです(コールバックなどからCADisplayLink
)。私たちのdisplayNow()
メソッドは to に通知CALayer
しdisplayIfNeeded()
、これは同期的に私たちにコールバックしdraw(_:,in:)
、 で描画を行い、internalDraw(_:)
先に進む前にコンテキストに描画されたものでビジュアルを更新します。
このアプローチは、上記の @RobNapier のものと似ていますが、displayIfNeeded()
に加えて呼び出すという利点がありsetNeedsDisplay()
、これにより同期が行われます。
これが可能なCALayer
のは、 が よりも多くの描画機能を公開しているためです。UIView
レイヤーはビューよりも下位レベルであり、レイアウト内で高度に構成可能な描画を目的として明示的に設計されており、(Cocoa の多くのものと同様に) 柔軟に使用できるように設計されています (親クラスとして、または委任者として、または他の描画システムへのブリッジとして、または単独で)。プロトコルを適切に使用することで、CALayerDelegate
これらすべてが可能になります。
CALayer
の設定可能性に関する詳細は、コア アニメーション プログラミング ガイド の「レイヤ オブジェクトの設定」セクションを参照してください。