保证退款、钢筋混凝土的方式来强制视图同步绘制 (在返回调用代码之前) 是配置CALayer 与您的UIView 子类的交互。
在您的 UIView 子类中,创建一个 displayNow() 方法,告诉图层“设置显示路线”然后“让它如此”:
斯威夫特
/// 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 都是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) 方法,以及故障安全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() 方法将告诉CALayer 到displayIfNeeded(),这将同步回调到我们的draw(_:,in:) 并在internalDraw(_:) 中进行绘制,在继续之前使用绘制到上下文中的内容更新视觉效果。
这种方法与上面的@RobNapier 类似,但优点是除了调用setNeedsDisplay() 之外还调用displayIfNeeded(),使其同步。
这是可能的,因为CALayers 比UIViews 公开了更多的绘图功能——层比视图低级,并且明确设计用于在布局中进行高度可配置的绘图,并且(就像在Cocoa)被设计为灵活使用(作为父类,或作为委托者,或作为与其他绘图系统的桥梁,或仅用于它们自己)。正确使用CALayerDelegate 协议使这一切成为可能。
有关CALayers 可配置性的更多信息,请参见Setting Up Layer Objects section of the Core Animation Programming Guide。