我无法截取WKWebView的屏幕截图。

6
我试图捕获WKWebView的屏幕截图,但是我的方法不起作用,它返回了一个纯色,就像图层树为空一样,而在其他视图上似乎可以工作。
- (UIImage *)screenshot
{
    UIImage *screenshot;

    UIGraphicsBeginImageContext(self.frame.size);

    [self.layer renderInContext:UIGraphicsGetCurrentContext()];

    screenshot = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return screenshot;
}

你找到iOS的解决方案了吗?目前我正在使用snapshotViewAfterScreenUpdates。但是我必须在webview渲染完成后才能调用它,所以我在didFinishNavigation中等待0.1秒并调用snapshotViewAfterScreenUpdates。这不是非常方便和可靠的方法。 - sidslog
遇到了与WKWebView视频录制相同的问题。它只是一个白色的正方形,而UIWebView可以正确地记录。目前似乎还没有找到解决方案。 - Dren
2
FYI,renderInContext 在 iOS 10 上可以使用,在 iOS 9 模拟器上也可以使用,但在 iOS 9 设备上不行。在测试时要小心。 - scosman
这个问题在2019年的iOS 12版本仍然困扰着我 - 非常不稳定的区域! - Andy Dent
7个回答

4
这个Stackoverflow答案帮助我在iOS 8上使用WKWebView解决了问题,其中[view snapshotViewAfterScreenUpdates:][view.layer renderInContext:]返回纯黑或白色。请注意保留HTML标记。
UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
UIImage* uiImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

1
值得注意的是,drawViewHierarchyInRect:afterScreenUpdates: 的返回值。如果您正在尝试通过在调用此方法之前临时调整视图的大小来呈现WKWebView的全部内容,则会发现该方法返回NO,表示未绘制所有内容,并且这将显示为所得UIImage中的灰色区域。 - user2067021

3
请参考此答案 iOS 11.0及以上版本,苹果提供了以下API来捕获WKWebView的快照。
@available(iOS 11.0, *)
    open func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, completionHandler: @escaping (UIImage?, Error?) -> Swift.Void)

示例用法:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

        if #available(iOS 11.0, *) {
            webView.takeSnapshot(with: nil) { (image, error) in
                //Do your stuff with image
            }
        }
    }

3

WKWebView仍然存在一个bug,但是可以通过使用另一个函数来解决:

[webView snapshotViewAfterScreenUpdates:NO or YES];

它有效。


2
这里有两个要点。在 iOS 10.3.1 之前,renderInContext 在 WKWebView 中的表现良好,但只有在呈现的视图层次结构中包含 WKWebView 时才有效。换句话说,系统正在将其绘制在屏幕上。
在 iOS 10.3.1 中,renderInContext 对我不起作用。同时,在 iOS 10.3.1 中,drawViewHierarchyInRect 表现良好。但只有在视图层次结构中时才有效!更糟糕的是,当我试图获取未显示在当前屏幕上的 WKWebView 的快照时,原始视图会失效。因此,截屏可能会破坏 WKWebView。
这是我的解决方法:
  1. 每次需要时,如果 WKWebView 在屏幕上,则使用 drawViewHierarchyInRect 保存一个快照(UIImage)。
  2. 如果 WKWebView 不在视图层次结构中,则使用已保存的快照。

1

drawViewHierarchyInRect方法可以工作,但会导致屏幕短暂闪烁。

如果需要高性能(快速捕获多个帧),我建议将WKWebView添加到窗口中的某个位置(即使使用frame偏移将其推出可见区域或使其透明)。我发现renderInContext更快,并且只要视图在窗口的视图层次结构中就可以正常工作。


0

我已经解决了问题,但需要以下几点:

  • WKWebView 必须在视图层次结构中,例如将其添加到根视图控制器中,将其发送到后面和/或隐藏它,直到您需要它。
  • yourWebView.frame 必须包含整个内容才能工作,我通过执行 yourWebView.frame = yourWebView.scrollView.contentSize 来实现。
  • 如果发现图像的某些部分需要裁剪,则存在设备内存的奇怪限制,请尝试将框架强制设置为更大或荒谬的大小,例如 10000 点,然后再次尝试呈现。
  • didFinish 委托方法有时会在真正的绘图发生之前被调用,当您进行绘制时还没有任何东西,我通过使用 perform(#selector(process(webView:)), with: webView, afterDelay: 0.01) 在短暂延迟后调用绘图例程来解决这个问题。

-1

试试这个

- (IBAction)takeScreenShot:(id)sender {

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
CGRect rect = [keyWindow bounds];
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[keyWindow.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIImageWriteToSavedPhotosAlbum(img, self,
                               @selector(image:didFinishSavingWithError:contextInfo:), nil);

}

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error
  contextInfo:(void *)contextInfo
{
// Was there an error?
if (error != NULL)
{
    // Show error message...
    UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Image not Saved" message:@"" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [alertView show];
}
else  // No errors
{
    // Show message image successfully saved
    UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"Image Saved" message:@"This chart has been save to your photos" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [alertView show];
}
}

1
不行,还是不起作用。我在截图中看到的图像与 WKWebView 应该显示的内容完全相同。只有网页的背景颜色存在于 WKWebView 的层树中。 - Vulkan
1
没有错误,因为在过程中没有出现任何问题。图层只是不在 Web 视图中。Web 视图图层只有一个图层。背景图层而已。这是一个巨大的 BUG! - Vulkan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接