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

发布于 2024-08-31 12:31:11 字数 827 浏览 5 评论 0原文

在我的代码中,我尝试在页面加载时显示 UIWebView ,然后在加载完成后,从 Web 视图中捕获图像以缓存并稍后显示(所以我没有重新加载并呈现网页)。

我有一些类似的事情:

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

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

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

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


更新:线程竞争条件可能是一个转移注意力的话题(无论如何,从文档中并不清楚,UIWebView的自定义层还是CATiledLayer 通常会阻塞其后台线程)。

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

我仍然遇到了一个问题,即以旧比例绘制了一些图块,但调用 renderInContext: 两次似乎已经充分缓解了这个问题。

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).

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.

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?


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).

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故人如初 2024-09-07 12:31:11

UIWebView 可能正在使用 CATiledLayer 或自定义衍生品。您也许可以用自己选择的东西替换图层,例如不执行线程绘制的简单 CALayer。在开始加载内容之前替换图层。

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

编辑:

来自 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. */

因此,您可以在调用 renderInContext: 之前将内容设置为 nil

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.

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.

Edit:

From 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:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文