您应该考虑使用NSOperation;要么是NSInvocationOperation,如果您有一个特定的对象进行渲染,或者NSBlockOperation,如果渲染足够简单以适合单个函数。
如果您可以在实际到达视图之前开始渲染drawRect:,那么就这样做(也许您的应用程序委托在启动时就开始该过程)。否则,检查drawRect:内容是否可用;如果没有,则开始操作并继续另一张图。当渲染对象完成其工作时,它可能会发布通知,或者,如果您给它返回视图的引用,则调用setNeedsDisplay:
按照最后一句的思路,您还可以考虑渲染对象能够返回部分渲染的图像。我不确定渲染的性质,但可能会在某些点(每 n 个循环的末尾,或每 n 行像素)获得结果,将其填充到NSImage与最终图像(如有必要,请在末尾进行填充),并使该部分图像可用于视图进行绘制。
更新: AnNSImage不“依赖”setNeedsDisplay:或具有视图引用,因为它不代表屏幕的一部分。它所做的只是包含图像的数据;它只能在视图中绘制自己,然后“显示”——实际上绘制在屏幕上。当您使用 时initByReferencingURL:,它会存储 URL,然后当另一个对象(例如包含图像并需要显示的视图)向它询问其内容时,它会执行如果您使用 时它会执行的操作initWithURL:,该对象是打开的文件并将其内容读入内存。但它并不懒惰地绘制;当视图正在绘制时,它只会绘制到需要它的视图中。
通过子类化NSImage来实现您自己的延迟加载或延迟渲染可能并不容易;它使用我认为是类簇一部分的辅助类,这就是为什么我建议拥有一个包含并返回NSImage.
更多的:
自定义视图的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.");
}
Run Code Online (Sandbox Code Playgroud)
由此输出的日志;请注意,实例化非常快,但加载和绘制需要两分钟,在此期间没有绘制任何内容,应用程序也没有执行任何其他操作(旋转沙滩球):
2011-04-27 21:33:00.899 SetNeedsDisplay[80162:a0b] 输入:drawRect: 2011-04-27 21:33:00.901 SetNeedsDisplay[80162:a0b] 图像实例化。 2011-04-27 21:34:57.911 SetNeedsDisplay[80162:a0b] 绘制的图像。 2011-04-27 21:34:57.912 SetNeedsDisplay[80162:a0b] 绘制贝塞尔曲线路径;退出绘制矩形。
| 归档时间: |
|
| 查看次数: |
852 次 |
| 最近记录: |