Cara yang dijamin uang kembali, diperkuat-beton-kokoh untuk memaksa tampilan menggambar secara sinkron (sebelum kembali ke kode panggilan) adalah dengan mengonfigurasi CALayer
interaksi dengan UIView
subkelas Anda .
Di subkelas UIView Anda, buat displayNow()
metode yang memberi tahu layer untuk " set course for display " lalu " make it so ":
Cepat
/// 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];
}
Juga terapkan draw(_: CALayer, in: CGContext)
metode yang akan memanggil metode gambar pribadi / internal Anda (yang berfungsi karena setiap UIView
adalah a CALayerDelegate
) :
Cepat
/// 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();
}
Dan buat internalDraw(_: CGRect)
metode kustom Anda , bersama dengan fail-safe draw(_: CGRect)
:
Cepat
/// 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];
}
Dan sekarang panggil saja myView.displayNow()
kapan pun Anda benar-benar membutuhkannya untuk menggambar (seperti dari CADisplayLink
panggilan balik) . displayNow()
Metode kami akan memberi tahu CALayer
kepada displayIfNeeded()
, yang akan secara sinkron memanggil kembali ke kami draw(_:,in:)
dan melakukan penggambaran internalDraw(_:)
, memperbarui visual dengan apa yang ditarik ke dalam konteks sebelum melanjutkan.
Pendekatan ini mirip dengan @ RobNapier di atas, tetapi memiliki keuntungan memanggil displayIfNeeded()
selain setNeedsDisplay()
, yang membuatnya sinkron.
Hal ini dimungkinkan karena CALayer
s mengekspos lebih banyak fungsionalitas menggambar daripada UIView
yang dilakukannya— lapisan adalah level yang lebih rendah daripada tampilan dan dirancang secara eksplisit untuk tujuan gambar yang sangat dapat dikonfigurasi dalam tata letak, dan (seperti banyak hal di Cocoa) dirancang untuk digunakan secara fleksibel ( sebagai kelas induk, atau sebagai delegator, atau sebagai jembatan ke sistem gambar lain, atau hanya sendiri). Penggunaan CALayerDelegate
protokol yang tepat memungkinkan semua ini.
Informasi lebih lanjut tentang konfigurasi CALayer
s dapat ditemukan di bagian Menyiapkan Objek Lapisan dari Panduan Pemrograman Animasi Inti .