วิธีที่รับประกันคืนเงินคอนกรีตเสริมเหล็กแข็งเพื่อบังคับให้มุมมองวาดแบบซิงโครนัส (ก่อนกลับไปที่รหัสการโทร)คือการกำหนดค่าการ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
เป็น a 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 ข้างต้น แต่มีข้อดีของการโทรdisplayIfNeeded()
นอกเหนือไปจากsetNeedsDisplay()
ซึ่งทำให้ซิงโครนัส
สิ่งนี้เป็นไปได้เนื่องจากCALayer
s แสดงฟังก์ชันการวาดมากกว่าUIView
ที่ทำ - เลเยอร์อยู่ในระดับที่ต่ำกว่ามุมมองและได้รับการออกแบบอย่างชัดเจนเพื่อจุดประสงค์ในการวาดที่กำหนดค่าได้สูงภายในเค้าโครงและ (เช่นเดียวกับหลาย ๆ อย่างใน Cocoa) ได้รับการออกแบบให้ใช้งานได้อย่างยืดหยุ่น ( ในฐานะคลาสแม่หรือในฐานะผู้แทนหรือเป็นสะพานเชื่อมไปยังระบบการวาดภาพอื่น ๆ หรือเพียงแค่ของพวกเขาเอง) การใช้งานไฟล์CALayerDelegate
โปรโตคอลอย่างเหมาะสมทำให้ทั้งหมดนี้เป็นไปได้
ข้อมูลเพิ่มเติมเกี่ยวกับ configurability ของCALayer
s สามารถพบได้ในการตั้งค่าชั้นส่วนของคอร์นิเมชั่นการเขียนโปรแกรมคู่มือวัตถุ