从-drawRect中调用-setNeedsDisplay:YES?

时间:2012-05-12 22:50:13

标签: objective-c cocoa osx-lion nsview drawrect

我正在自定义我的drawRect:方法,如果它已被“加载”,则用于绘制NSImage(加载花费几秒钟的时间,因为我从{{{{}获取它1}}),如果图像尚未加载,则推迟将图像绘制到后面。

WebView

我的问题是如何做后者。如果图片不可用,- (void)drawRect:(NSRect)dirtyRect { NSImage *imageToDraw = [self cachedImage]; if (imageToDraw != nil) { [imageToDraw drawInRect:dirtyRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0 respectFlipped:YES hints:nil]; } else { //I need help here [self setNeedsDisplay:YES]; } } 会返回[self cachedImage],但在接下来的几秒钟内它可能会变得可用,此时我想绘制它,因为自定义视图已经在屏幕上。

我最初的本能是尝试调用nil,如果图像不可用,希望它会告诉Cocoa下次再次呼叫[self setNeedsDisplay:YES];(并且一次又一次地再次呼叫drawRect图像被绘制),但这不起作用。

关于我可以从这里去哪里的任何指示?


编辑:

我非常了解在完全处理loadRequest时触发的WebView的委托方法。然而,由于应用程序其余部分的结构,使用这些将非常困难,但我想我会尝试以某种方式使用它们现在给出当前的答案。 (另请注意,我的drawRect:方法相对较轻,除了上面已有的代码之外没有。)

我目前有大约10多个自定义视图,每个视图都有自定义数据,要求相同的WebView为每个自定义数据生成图像。同时,我从NSCache中获取图像(使用与每个自定义视图对应的标识符),如果它不存在或需要更新则创建它,如果它尚不可用则返回nil。因此,它并不像从- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame或其他方法调用[view setNeedsDisplay:YES]那么容易。

3 个答案:

答案 0 :(得分:4)

  

我最初的本能是尝试调用[self setNeedsDisplay:YES];如果图像不可用,希望它能告诉Cocoa下次再次调用drawRect(并且一次又一次地再次调用图像)

即使有效,这也会非常低效。

  

在接下来的几秒钟内随时可以使用,当时我想画它

因此,当发生这种情况时,请致电[view setNeedsDisplay:YES]

如果您无法直接确定图像何时可用,则必须进行轮询。设置一个重复NSTimer,间隔为合理的间隔 - 比如0.25秒左右。 (这也是非常低效的,但至少它每秒只运行4次而不是60或更差。这是两个因素之间的权衡:你想要使用多少CPU和电池电量,以及延迟时间多长图像变得可用以及显示它的时间。)

  

我的drawRect:方法相对较轻,除了上面已有的代码之外什么也没有。

即使你在-drawRect:中什么都不做,Cocoa仍然需要在幕后做很多工作 - 它需要管理脏的部分,清除窗口后备存储的适当区域,冲洗它屏幕等等。这些都不是免费的。

答案 1 :(得分:1)

好吧,通常会在下载某些内容时调用一些委托方法。您应该实现该方法并在那里调用setNeedsDisplay:YES

答案 2 :(得分:0)

webkit的文档:

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DisplayWebContent/Tasks/ResourceLoading.html#//apple_ref/doc/uid/20002028-CJBEHAAG

您必须在webview委托中实施以下方法:

 - webView:resource:didFinishLoadingFromDataSource: 

您可以拨打[view setNeedsDisplay:Yes]