Gwarantowany zwrot pieniędzy, solidny sposób na wymuszenie synchronicznego rysowania widoku (przed powrotem do kodu wywołującego) polega na skonfigurowaniu CALayerinterakcji między UIViewpodklasą.
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 UIViewjest 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 CADisplayLinkoddzwonienia) . Nasza displayNow()metoda powie CALayerto 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ż CALayerudostępniają one więcej funkcji rysowania niż inne - UIViewwarstwy 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 CALayerDelegateprotokołu.
Więcej informacji na temat konfigurowalności CALayers można znaleźć w sekcji Setting Up Layer Objects w przewodniku Core Animation Programming Guide .