如何判断UIWebView何时完成绘制到上下文?

时间:2022-09-24 19:44:11

In my code I'm trying to show a UIWebView as a page is loading, and then, when it's done, capture an image from the web view to cache and display later (so I don't have to reload and render the web page).

在我的代码中,我试图在页面加载时显示UIWebView,然后,当它完成时,从Web视图捕获图像以便稍后缓存和显示(因此我不必重新加载和呈现网页)。

I have something along the lines of:

我有类似的东西:

CGContextRef context = CGBitmapContextCreate(…);
[[webView layer] renderInContext:context];

CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage *image = [UIImage imageWithCGImage:imageRef];

The problem I'm running into is that, due to UIWebView's tiling, sometimes only half of the page is rendered to the context by the time I capture the image.

我遇到的问题是,由于UIWebView的平铺,有时在我捕获图像时,只有一半的页面被渲染到上下文中。

Is there a way to detect or block on UIWebView's background rendering thread so that I can get the image only after all of the rendering has finished?

有没有办法检测或阻止UIWebView的后台渲染线程,这样我才能在所有渲染完成后才能获取图像?


UPDATE: It may be that thread race conditions were a red herring (it's unclear from the documentation, at any rate, whether UIWebView's custom layer or a CATiledLayer in general blocks on its background threads).

更新:可能是线程竞争条件是一个红色鲱鱼(从文档中不清楚,无论是UIWebView的自定义层还是CATiledLayer在其后台线程中的一般块)。

This may instead have been an invalidation issue (despite several sorts of calls to setNeedsDisplay on both the UIWebView and its layer). Changing the bounds of the UIWebView before rendering it appears to have eliminated the "not drawing the whole thing" problem.

这可能是一个失效问题(尽管在UIWebView及其图层上对setNeedsDisplay进行了几种调用)。在渲染之前更改UIWebView的边界似乎已经消除了“不绘制整个事物”的问题。

I still ran into a problem where a few tiles were being drawn at the old scale, but calling renderInContext: twice seems to have mitigated that sufficiently.

我仍然遇到了一个问题,即在旧规模上绘制了几个图块,但调用renderInContext:两次似乎已经足够缓解了这个问题。

1 个解决方案

#1


0  

UIWebView is probably using a CATiledLayer or custom derivative. You may be able to replace the layer with something of your own choosing such as a simple CALayer which does not do threaded drawing. Replace the layer before you start loading content.

UIWebView可能使用CATiledLayer或自定义派生。您可以使用自己选择的内容替换图层,例如不进行螺纹绘图的简单CALayer。在开始加载内容之前替换图层。

If replacing the layer with a standard CALayer does not work, you may have to make your own subclass that emulates the behavior of a CATiledLayer without actually being threaded.

如果用标准CALayer替换图层不起作用,则可能必须创建自己的子类来模拟CATiledLayer的行为,而不实际使用线程。

Edit:

编辑:

From CATiledLayer.h

来自CATiledLayer.h

/* Note: do not attempt to directly modify the `contents' property of
 * an CATiledLayer object - doing so will effectively turn it into a
 * regular CALayer. */

So you may just be able to set the contents to nil before calling renderInContext:

所以你可以在调用renderInContext之前将内容设置为nil:

#1


0  

UIWebView is probably using a CATiledLayer or custom derivative. You may be able to replace the layer with something of your own choosing such as a simple CALayer which does not do threaded drawing. Replace the layer before you start loading content.

UIWebView可能使用CATiledLayer或自定义派生。您可以使用自己选择的内容替换图层,例如不进行螺纹绘图的简单CALayer。在开始加载内容之前替换图层。

If replacing the layer with a standard CALayer does not work, you may have to make your own subclass that emulates the behavior of a CATiledLayer without actually being threaded.

如果用标准CALayer替换图层不起作用,则可能必须创建自己的子类来模拟CATiledLayer的行为,而不实际使用线程。

Edit:

编辑:

From CATiledLayer.h

来自CATiledLayer.h

/* Note: do not attempt to directly modify the `contents' property of
 * an CATiledLayer object - doing so will effectively turn it into a
 * regular CALayer. */

So you may just be able to set the contents to nil before calling renderInContext:

所以你可以在调用renderInContext之前将内容设置为nil: