Гарантований поверненням грошей, залізобетонним твердим способом змусити подати погляд на синхронний малюнок (перед поверненням до викликового коду) - це налаштувати 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()
}
Ціль-С
/// 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()
}
Ціль-С
/// 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)
}
Ціль-С
/// 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, але має перевагу displayIfNeeded()
додаткового виклику setNeedsDisplay()
, що робить його синхронним.
Це можливо, тому CALayer
що експонуйте більше функціональних можливостей малювання, ніж UIView
у нас - шари нижчого рівня, ніж представлення, і явно розроблені для малюнка, що легко налаштовується в макеті, і (як і багато речей у какао) призначені для гнучкого використання ( як батьківський клас, або як делегатор, або як міст до інших систем малювання, або просто самостійно). Правильне використання CALayerDelegate
протоколу робить все це можливим.
Більш детальну інформацію про налаштування CALayer
s можна отримати в розділі Налаштування об'єктів шару в Посібнику з основних анімаційних програм .