Search code examples
iosswiftwkwebviewxcode9-beta

WKWebView's (beta) takeSnapshot method, how to implement?


I noticed the WKWebView documentation now lists a method called takeSnapshot that is supported by iOS 11 and macOS 10.13 and above (Xcode 9 beta).

Has anyone played around with yet or implemented? I'm trying to get it working in a playground but I'm not sure where to start? Is this a method on a WKWebView?

My code:

import UIKit
import PlaygroundSupport
import WebKit



let frame = CGRect(x: 0, y: 0, width: 800, height:600)
let web = WKWebView(frame: frame)
let rq = URLRequest(url: NSURL(string: "http://apple.com")! as URL)
web.load(rq)
PlaygroundPage.current.liveView = web
PlaygroundPage.current.needsIndefiniteExecution = true

//Take snapshot?

Solution

  • As far as I tested, the method takeSnapshot(with:completionHandler:) actually exists as an instance method and works as expected.

    Just that it's a little hard to use it.

    The method declares its first parameter as WKSnapshotConfiguration?, but the class WKSnapshotConfiguration is not imported with import WebKit. You can pass nil to the parameter, but to use the method, you need to import the type WKSnapshotConfiguration. And I could not have found any dependent submodules to import WKSnapshotConfiguration.

    So, if you want to play with this new feature, you need to create an App project with bridging-header. (If you know how to use bridging-header in the Playground, you may test this feature in it. But I do not know if you can or how.)

    {ProjectName}-Bridging-Header.h:

    @import CoreGraphics;
    #import <WebKit/WKSnapshotConfiguration.h>
    

    And an example of ViewController.swift:

    import UIKit
    import WebKit
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var webView: WKWebView!
        @IBOutlet weak var imageView: UIImageView!
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let request = URLRequest(url: URL(string: "http://apple.com")!)
            webView.load(request)
        }
    
        @IBAction func buttonPressed(_ sender: UIButton) {
            webView.takeSnapshot(with: nil) {image, error in
                if let image = image {
                    self.imageView.image = image
                    print("Got snapshot")
                } else {
                    print("Failed taking snapshot: \(error?.localizedDescription ?? "--")")
                }
            }
        }
    
    }
    

    (Place a WKWebView, a UIImageView and a UIButton on a View.)


    One more, this seems to be a bug of WebKit framework, you should better send a bug report to Apple.