La forma de devolución de dinero garantizada, de hormigón armado y sólido de forzar a que una vista se dibuje sincrónicamente (antes de volver al código de llamada) es configurar las CALayer
interacciones de the con su UIView
subclase.
En su subclase UIView, cree un displayNow()
método que le diga a la capa que " establezca el rumbo para la visualización " y luego "lo haga así ":
Rápido
/// 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()
}
C objetivo
/// 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];
}
También implemente un draw(_: CALayer, in: CGContext)
método que llamará a su método de dibujo privado / interno (que funciona ya que cada UIView
es a CALayerDelegate
) :
Rápido
/// 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()
}
C objetivo
/// 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();
}
Y cree su internalDraw(_: CGRect)
método personalizado , junto con a prueba de fallas draw(_: CGRect)
:
Rápido
/// 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)
}
C objetivo
/// 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];
}
Y ahora solo llame myView.displayNow()
cuando realmente lo necesite para dibujar (como desde una CADisplayLink
devolución de llamada) . Nuestro displayNow()
método le dirá CALayer
a displayIfNeeded()
, que llamará de forma sincrónica a nuestro draw(_:,in:)
y hará el dibujo internalDraw(_:)
, actualizando lo visual con lo que se dibuja en el contexto antes de continuar.
Este enfoque es similar al de @ RobNapier anterior, pero tiene la ventaja de llamar displayIfNeeded()
además de setNeedsDisplay()
, lo que lo hace sincrónico.
Esto es posible porque los CALayer
s exponen más funciones de dibujo que los UIView
s: las capas tienen un nivel más bajo que las vistas y están diseñadas explícitamente con el propósito de un dibujo altamente configurable dentro del diseño y (como muchas cosas en Cocoa) están diseñadas para usarse de manera flexible ( como clase principal, o como delegador, o como puente a otros sistemas de dibujo, o simplemente por sí mismos). El uso adecuado del CALayerDelegate
protocolo hace que todo esto sea posible.
CALayer
Puede encontrar más información sobre la capacidad de configuración de s en la sección Configuración de objetos de capa de la Guía de programación de animación principal .