Linh cảm của bạn là đúng, đây thực sự là một cách tuyệt vời để tối ưu hóa bản vẽ. Tôi đã tự làm nó ở nơi tôi có một số nền tĩnh lớn mà tôi muốn tránh vẽ lại khi các yếu tố di chuyển lên trên.
Tất cả những gì bạn cần làm là thêm CALayer
đối tượng cho từng mục nội dung trong chế độ xem của bạn. Để vẽ các lớp, bạn nên đặt chế độ xem làm đại biểu cho từng lớp và sau đó triển khai phương thức drawLayer:inContext:
.
Trong phương pháp mà bạn chỉ cần vẽ các nội dung của mỗi lớp:
- (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx
{
if(layer == yourBackgroundLayer)
{
//draw your background content in the context
//you can either use Quartz drawing directly in the CGContextRef,
//or if you want to use the Cocoa drawing objects you can do this:
NSGraphicsContext* drawingContext = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES];
NSGraphicsContext* previousContext = [NSGraphicsContext currentContext];
[NSGraphicsContext setCurrentContext:drawingContext];
[NSGraphicsContext saveGraphicsState];
//draw some stuff with NSBezierPath etc
[NSGraphicsContext restoreGraphicsState];
[NSGraphicsContext setCurrentContext:previousContext];
}
else if (layer == someOtherLayer)
{
//draw other layer
}
//etc etc
}
Khi bạn muốn cập nhật nội dung của một trong các lớp, chỉ cần gọi [yourLayer setNeedsDisplay]
. Điều này sau đó sẽ gọi phương thức ủy nhiệm ở trên để cung cấp nội dung cập nhật của lớp.
Lưu ý rằng theo mặc định, khi bạn thay đổi nội dung lớp, Core Animation cung cấp một chuyển đổi mờ dần đẹp cho nội dung mới. Tuy nhiên, nếu bạn đang xử lý bản vẽ, có thể bạn không muốn điều này, vì vậy để tránh làm mờ hoạt ảnh mặc định khi nội dung của lớp thay đổi, bạn cũng phải triển khai phương thức ủy quyền actionForLayer:forKey:
và ngăn hoạt ảnh bằng cách trả về hành động rỗng:
- (id<CAAction>)actionForLayer:(CALayer*)layer forKey:(NSString*)key
{
if(layer == someLayer)
{
//we don't want to animate new content in and out
if([key isEqualToString:@"contents"])
{
return (id<CAAction>)[NSNull null];
}
}
//the default action for everything else
return nil;
}
Nguồn
2012-02-21 12:23:46
Cảm ơn, điều này rất hữu ích. Tuy nhiên, tôi đang gặp khó khăn trong việc đưa phương thức ủy nhiệm để kích hoạt. Tôi thiết lập quan điểm của tôi với tư cách là người đại diện và tôi đang thêm các lớp làm lớp con của lớp gốc, và tôi đang gọi 'setNeedsDisplay' nhưng' drawLayer: inContext' không bao giờ được gọi. Ý tưởng nào? – mtmurdock
Bạn có thể đăng mã của mình không? Điều này sẽ làm việc. –
Tôi cũng ghi đè 'drawRect:' có thể khiến nó không gọi hàm kia không? – mtmurdock