【问题标题】:I can't capture the screenshot of a WKWebView我无法捕获 WKWebView 的屏幕截图
【发布时间】:2014-11-10 12:26:02
【问题描述】:

我正在尝试捕获 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。不是很方便和可靠(
  • WKWebView 的视频录制也遇到了同样的问题。它只是一个白色方块,而 UIWebView 记录正确。看起来还没有找到决定
  • 仅供参考,renderInContext 适用于 iOS 10,适用于 iOS 9 的模拟器,但不适用于配备 iOS 9 的设备。请小心测试。
  • 这仍然困扰着我 2019 年的 iOS 12 - 非常不稳定的区域!

标签: ios objective-c iphone uiview wkwebview


【解决方案1】:

Stackoverflow answer 在 iOS 8 上使用 WKWebView 为我解决了这个问题,其中 [view snapshotViewAfterScreenUpdates:][view.layer renderInContext:] 返回纯黑色或纯白色:

UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
UIImage* uiImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

【讨论】:

  • 不过drawViewHierarchyInRect:afterScreenUpdates:的返回值还是值得关注的。如果您尝试在调用此方法之前通过临时调整视图大小来呈现 WKWebView 的全部内容,我发现该方法返回 NO,表示未绘制所有内容,并且这显示为灰色区域生成的 UIImage。
【解决方案2】:

WKWebView 仍然存在一个错误,但您可以通过使用另一个函数来解决它:

[webView snapshotViewAfterScreenUpdates:NO or YES];

有效。

【讨论】:

    【解决方案3】:

    请参考这个answer

    iOS 11.0 及以上版本,Apple 提供了以下 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
                }
            }
        }
    

    【讨论】:

      【解决方案4】:

      drawViewHierarchyInRect 方法会起作用,但会导致屏幕短暂闪烁。

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

      【讨论】:

        【解决方案5】:

        这是我的两点。在 iOS 10.3.1 之前,renderInContext 用于 WKWebView。但前提是 WKWebView 包含在呈现的视图层次结构中。换句话说,系统正在屏幕上绘制它。

        在 iOS 10.3.1 中,renderInContext 不适用于我。同时,drawViewHierarchyInRect 在 iOS 10.3.1 中运行良好。 但只有在视图层次结构中!更糟。当我试图获取当前屏幕上未显示的 WKWebView 的快照时,原始视图变得无效。因此截屏可能会破坏 WKWebView。

        这是我的解决方法。

        1. 每次需要时,我都会使用drawViewHierarchyInRect 保存快照 (UIImage)。但前提是 WKWebView 在屏幕上。
        2. 如果 WKWebView 不在视图层次结构中,我将使用保存的快照。

        【讨论】:

          【解决方案6】:

          我得到了它的工作,但需要以下东西:

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

          【讨论】:

            【解决方案7】:

            试试这个

            - (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];
            }
            }
            

            【讨论】:

            • Nup,还是不行。我在 WKWebView 应该在的屏幕截图中得到完全相同的图像。 WKWebView的图层树中只存在网页的背景色。
            • 没有错误,因为过程中没有出错。这些图层只是不在 Web 视图中。 Web 视图层只有 1 层。背景层。就是这样......这是一个巨大的错误!
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-08-30
            • 2015-05-16
            • 2011-10-13
            • 1970-01-01
            • 2012-01-20
            • 1970-01-01
            相关资源
            最近更新 更多