我有一个需要根据需要绘制到图形上下文的对象,但是,当调用对象draw方法时,内容需要时间渲染并且可能不可用。
这一般如何实现?存储对图形上下文或视图请求绘图的引用,并在完全呈现对象内部表示时延迟绘制它?
还是有其他标准的可可机制来处理这个问题(例如NSImage
在使用NSURL
初始化时进行延迟绘制)?
澄清:
NSView
-setNeedsDisplay:
不是我要找的答案(NSImage
不依赖-setNeedsDisplay:
)答案 0 :(得分:1)
我喜欢EGOImageView类用于这些目的。它非常容易使用并且包括一些很好的奖励,例如缓存机制。
在此处阅读有关EGOImageView的更多信息(包括Github的下载链接):
http://developers.enormego.com/view/what_if_images_on_the_iphone_were_as_easy_as_html
答案 1 :(得分:1)
你应该考虑使用NSOperation;如果您有特定对象进行渲染,则为NSInvocationOperation
;如果渲染足够简单以适合单个函数,则为NSBlockOperation
。
如果您可以在实际访问视图drawRect:
之前开始渲染,那么就这样做(也许您的应用代表会在启动时启动该过程)。否则,请检查drawRect:
内容是否仍然可用;如果没有,请启动操作并继续其他绘图。当渲染对象完成其工作时,它可能会发布通知,或者,如果您向视图提供引用,请调用setNeedsDisplay:
沿着最后一句话,您还可以考虑渲染对象能够返回部分渲染的图像。我不确定渲染的性质,但有可能在某些点(每个n循环的末尾,或每n行像素)得到结果,将它们放入单独的NSImage
中与最终图像大小相同(如果需要,在末尾填充),并使该部分图像可用于绘图。
更新:NSImage
不“依赖”setNeedsDisplay:
或拥有视图参考,因为它不代表屏幕的一部分。它所做的就是包含图像的数据;它只能在里面绘制一个视图,然后“显示” - 实际上在屏幕上绘制。当您使用initByReferencingURL:
时,它会存储URL,然后当另一个对象(如包含图像并需要显示的视图)询问其内容时,它会执行如果您拥有它将会执行的操作使用initWithURL:
,它打开文件并将其内容读入内存。但是,它并不懒惰地绘制;它只会将绘制到想要它的视图中,当该视图正在绘制时。
对NSImage
进行子类化以实现自己的延迟加载或延迟渲染可能并不容易;它使用我认为是class cluster的一部分的辅助类,这就是为什么我建议使用一个包含并返回NSImage
的“渲染器”对象。
MORE:
自定义视图drawRect
:
- (void)drawRect:(NSRect)dirtyRect {
NSLog(@"Entered: %@", NSStringFromSelector(_cmd));
// Use a nice big image of the Milky Way -- this is about 5MB
NSImage * lazyImage = [[[NSImage alloc] initByReferencingURL:
[NSURL URLWithString:@"http://www.eso.org/public/archives/images/original/milkyway.jpg"]]
autorelease];
NSLog(@"Image instantiated.");
[lazyImage drawInRect:[self bounds] fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
NSLog(@"Image drawn"); // 2 minutes later; sometimes 3 in my testing
[[NSColor yellowColor] set];
[[NSBezierPath bezierPathWithRect:NSInsetRect([self bounds], 4, 4)] stroke];
NSLog(@"Bezier path drawn; exiting drawRect.");
}
此日志输出;注意实例化非常快,但是加载和绘图需要两分钟,在此期间什么都没画,应用程序什么都不做(旋转沙滩球):
2011-04-27 21:33:00.899 SetNeedsDisplay[80162:a0b] Entered: drawRect: 2011-04-27 21:33:00.901 SetNeedsDisplay[80162:a0b] Image instantiated. 2011-04-27 21:34:57.911 SetNeedsDisplay[80162:a0b] Image drawn. 2011-04-27 21:34:57.912 SetNeedsDisplay[80162:a0b] Bezier path drawn; exiting drawRect.