Gwarantowany zwrot pieniędzy, solidny sposób na wymuszenie synchronicznego rysowania widoku (przed powrotem do kodu wywołującego) polega na skonfigurowaniu CALayer
interakcji między UIView
podklasą.
W swojej podklasie UIView utwórz displayNow()
metodę, która powie warstwie, aby „ ustawiła kurs wyświetlania ”, a następnie „ uczyniła to ”:
Szybki
/// 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()
}
Cel 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];
}
Zaimplementuj także draw(_: CALayer, in: CGContext)
metodę, która wywoła twoją prywatną / wewnętrzną metodę rysowania (która działa, ponieważ każdy UIView
jest a CALayerDelegate
) :
Szybki
/// 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()
}
Cel 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();
}
I stwórz własną internalDraw(_: CGRect)
metodę wraz z niezawodnością draw(_: CGRect)
:
Szybki
/// 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)
}
Cel 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];
}
A teraz po prostu zadzwoń, myView.displayNow()
kiedy naprawdę - naprawdę potrzebujesz go do rysowania (na przykład z CADisplayLink
oddzwonienia) . Nasza displayNow()
metoda powie CALayer
to displayIfNeeded()
, co będzie synchronicznie wywoływać z powrotem do naszego draw(_:,in:)
i rysować internalDraw(_:)
, aktualizując wizualizację o to, co zostało wciągnięte w kontekst, zanim przejdziemy dalej.
To podejście jest podobne do powyższego @ RobNapier, ale ma tę zaletę, że displayIfNeeded()
oprócz wywoływania setNeedsDisplay()
jest synchroniczne.
Jest to możliwe, ponieważ CALayer
udostępniają one więcej funkcji rysowania niż inne - UIView
warstwy są niższego poziomu niż widoki i zaprojektowane specjalnie w celu tworzenia wysoce konfigurowalnych rysunków w układzie i (podobnie jak wiele rzeczy w kakao) są zaprojektowane tak, aby można było ich używać elastycznie ( jako klasa nadrzędna lub delegator, lub jako pomost do innych systemów rysowania lub po prostu samodzielnie). To wszystko umożliwia właściwe wykorzystanie CALayerDelegate
protokołu.
Więcej informacji na temat konfigurowalności CALayer
s można znaleźć w sekcji Setting Up Layer Objects w przewodniku Core Animation Programming Guide .