I can't capture the screenshot of a WKWebView

2019-04-09 17:56发布

I'm trying to capture a screenshot of a WKWebView but my method doesn't work properly, it returns a solid color as if the layer tree was empty, while it seems to work on other views.

- (UIImage *)screenshot
{
    UIImage *screenshot;

    UIGraphicsBeginImageContext(self.frame.size);

    [self.layer renderInContext:UIGraphicsGetCurrentContext()];

    screenshot = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return screenshot;
}

6条回答
再贱就再见
2楼-- · 2019-04-09 18:22

There's still a bug with the WKWebView but you can work your way around it by using another function:

[webView snapshotViewAfterScreenUpdates:NO or YES];

It works.

查看更多
3楼-- · 2019-04-09 18:25

Try this

- (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];
}
}
查看更多
爷的心禁止访问
4楼-- · 2019-04-09 18:30

Please refer to this answer

iOS 11.0 and above, Apple has provided following API to capture snapshot of WKWebView.

@available(iOS 11.0, *)
    open func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, completionHandler: @escaping (UIImage?, Error?) -> Swift.Void)

Sample usage:

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

        if #available(iOS 11.0, *) {
            webView.takeSnapshot(with: nil) { (image, error) in
                //Do your stuff with image
            }
        }
    }
查看更多
太酷不给撩
5楼-- · 2019-04-09 18:33

The drawViewHierarchyInRect method will work, but will cause the screen to briefly flash.

If you need high performance (capturing many frames quickly), I suggest adding the WKWebView to your window somewhere (even if you push it out of the visible area with the frame offset or make it transparent). I found that renderInContext is much faster, and works fine as long as the view is in the view hierarchy of the window.

查看更多
在下西门庆
6楼-- · 2019-04-09 18:39

This Stackoverflow answer solved it for me on iOS 8 with a WKWebView where [view snapshotViewAfterScreenUpdates:] and [view.layer renderInContext:] either returned solid black or white:

UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
UIImage* uiImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
查看更多
倾城 Initia
7楼-- · 2019-04-09 18:42

Here are my two points. Before the iOS 10.3.1 renderInContext used to work well for the WKWebView. But only if a WKWebView is included in a presented view hierarchy. In other words, the system is drawing it on the screen.

In the iOS 10.3.1, renderInContext doesn't work for me. In the same moment, drawViewHierarchyInRect works fine in the iOS 10.3.1. But only if it's in the view hierarchy! Even worse. When I was trying to get a snapshot of the WKWebView, which wasn't presented on the current screen, the original view became invalidated. Thus taking screenshot can break a WKWebView.

Here is my workaround.

  1. I save a snapshot (UIImage) with drawViewHierarchyInRect every time when I need it. But only if the WKWebView is on the screen.
  2. If the WKWebView isn't in the view hierarchy I use a saved snapshot.
查看更多
登录 后发表回答