如何捕获WKWebview的整页截图?

时间:2016-02-15 10:31:31

标签: ios wkwebview

我可以通过调整UIWebView UIScrollView的框架来捕获UIWebView的所有内容屏幕截图。但是,我无法通过相同的方法捕获WKWebView的所有内容屏幕截图。

我用于捕获UIWebView的方法如下:

  1. webview.scrollView
  2. 的备用框架和超级视图
  3. 创建一个新的容器视图webview.scrollView的超级视图
  4. 调整新容器视图的框架和webview.scrollView。框架与webview.scrollView.contentSize
  5. 相同
  6. renderInContextdrawViewHierarchyInRect
  7. 绘制

    但是,此方法将捕获WKWebview的白色屏幕截图。它没有用!

    我打印了WKWebView的所有级别,然后我发现UIView(WKContentView)的大小与contentView相同,您可以在此级别找到此视图:

    • WKWebView
      • WKScrollView
        • WKContentView(大小与contentView相同)

    我也尝试按WKContentView捕获,然后我发现只能抓取可见的视图。

    无论如何,任何人都可以告诉我如何捕获WKWebView的完整页面内容屏幕截图?

6 个答案:

答案 0 :(得分:5)

请参阅此answer

iOS 11.0及更高版本,Apple提供了以下API来捕获WKWebView的快照。

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

答案 1 :(得分:3)

Swift 3,Xcode 8

func takeScreenshot() -> UIImage? { 
    let currentSize = webView.frame.size
    let currentOffset = webView.scrollView.contentOffset

    webView.frame.size = webView.scrollView.contentSize
    webView.scrollView.setContentOffset(CGPoint.zero, animated: false)

    let rect = CGRect(x: 0, y: 0, width: webView.bounds.size.width, height: webView.bounds.size.height)
    UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
    webView.drawHierarchy(in: rect, afterScreenUpdates: true)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    webView.frame.size = currentSize
    webView.scrollView.setContentOffset(currentOffset, animated: false)

    return image
}

答案 2 :(得分:1)

-xcode 10和swift 4.2-

使用它;

//这是获取屏幕截图的按钮

   @IBAction func snapShot(_ sender: Any) {

       captureScreenshot()
    }

//这是处理屏幕截图功能的功能。

func captureScreenshot(){
    let layer = UIApplication.shared.keyWindow!.layer
    let scale = UIScreen.main.scale
    // Creates UIImage of same size as view
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
    layer.render(in: UIGraphicsGetCurrentContext()!)
    let screenshot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    // THIS IS TO SAVE SCREENSHOT TO PHOTOS
    UIImageWriteToSavedPhotosAlbum(screenshot!, nil, nil, nil)
}

,您必须将这些密钥添加到info.plist;

 key value = "Privacy - Photo Library Additions Usage Description" ,
 key value = Privacy - Photo Library Usage Description

答案 3 :(得分:0)

Swift 3,Xcode 9: 我创建了一个扩展来实现这一目标。希望这会对你有所帮助。

class MasterViewController: UIViewController {

    var masters = [Master]()

    override func viewDidLoad() {
        super.viewDidLoad()

        // add array with 10 players with hp points
        masters.append(Master(playerName: "John Doe", hp: 100, avatar: nil))
        masters.append(Master(playerName: "Jack Jones", hp: 50, avatar: nil))
        masters.append(Master(playerName: "Susan Scott", hp: 150, avatar: nil))
        // Add any masters here ...
        // Another way of doing it : (0..<10).forEach { masters.append(Master(playerName: ""+$0, hp: 12 + $0, avatar: nil)) }

        // filter array to return alive players
        let aliveMasters = masters.filter { $0.isAlive }

        // map the resulenter code hereting array and display this table as a list.
        // Here aliveMasters is already an array of Masters, map is used to "transform" data
        let mappedMasters: [String] = masters.map { $0.playerName }
        print("Alive Masters are : \(mappedMasters)")

    }

}

答案 4 :(得分:0)

这是一个 iOS 11+ 示例,用于对 WKWebView 进行快照无需任何延迟来呈现内容。

关键是确保您不会收到空白快照。最初,我们遇到了输出图像为空白的问题,并且必须引入延迟才能在输出图像中包含 Web 内容。我在许多帖子中看到了延迟的解决方案,我建议不要使用它,因为它是一个不必要的不​​可靠和性能不佳的解决方案。对我们来说重要的解决方案是设置 rectWKSnapshotConfiguration 并使用 JavaScript 函数等待渲染并接收正确的宽度和高度。

设置 WKWebView:

// Important: You can set a width here which will also be reflected in the width of the snapshot later
let webView = WKWebView(frame: .zero)

webView.configuration.dataDetectorTypes = []
webView.navigationDelegate = self

webView.scrollView.contentInsetAdjustmentBehavior = .never

webView.loadHTMLString(htmlString, baseURL: Bundle.main.resourceURL)

捕获快照:

func webView(
    _ webView: WKWebView,
    didFinish navigation: WKNavigation!
) {
    // Wait for the page to be rendered completely and get the final size from javascript
    webView.evaluateJavaScript("document.readyState", completionHandler: { [weak self] (readyState, readyStateError) in
        webView.evaluateJavaScript("document.documentElement.scrollWidth", completionHandler: {(contentWidth, widthError) in
            webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { (contentHeight, heightError) in
                guard readyState != nil,
                    let contentHeight = contentHeight as? CGFloat,
                    let contentWidth = contentWidth as? CGFloat else {
                    [Potential error handling...]
                    return
                }

                let rect = CGRect(
                    x: 0,
                    y: 0,
                    width: contentWidth,
                    height: contentHeight
                )

                let configuration = WKSnapshotConfiguration()

                configuration.rect = rect

                if #available(iOS 13.0, *) {
                    configuration.afterScreenUpdates =  true
                }

                webView.takeSnapshot(with: configuration) { (snapshotImage, error) in
                    guard let snapshotImage = snapshotImage else {
                        [Potential error handling...]
                    }

                    [Do something with the image]
                }
            })
        })
    })
}

答案 5 :(得分:-2)

更新:不确定为什么Jason会在整个网络上坚持这个答案。它没有解决如何截取整个WKWebView内容的问题......包括屏幕外的内容。

试试这个:

func snapshot() -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.webView.bounds.size, true, 0);
        self.webView.drawViewHierarchyInRect(self.webView.bounds, afterScreenUpdates: true);
        let snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        UIImageWriteToSavedPhotosAlbum(snapshotImage, nil, nil, nil)

        return snapshotImage
    }

图像将自动保存到iOS相机胶卷(通过UIImageWriteToSavedPhotosAlbum())。