Search code examples
swiftmacoscocoawkwebview

WKWebView CALayer to image exports blank image


I'm trying to take a screenshot of webpage but the image is always blank(white).

I'm using this code to convert CALayer to Data(taken from here)

extension CALayer {

/// Get `Data` representation of the layer.
///
/// - Parameters:
///   - fileType: The format of file. Defaults to PNG.
///   - properties: A dictionary that contains key-value pairs specifying image properties.
///
/// - Returns: `Data` for image.

func data(using fileType: NSBitmapImageFileType = .PNG, properties: [String : Any] = [:]) -> Data {
    let width = Int(bounds.width * self.contentsScale)
    let height = Int(bounds.height * self.contentsScale)
    let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)!
    imageRepresentation.size = bounds.size

    let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!

    render(in: context.cgContext)

    return imageRepresentation.representation(using: fileType, properties: properties)!
}

}

And then to write the data to file as .png

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) 
{
    let d = web.layer?.data() as NSData?  //web is the instance of WKWebView
    d!.write(toFile: "/Users/mac/Desktop/web.png", atomically: true)
}

But I'm getting a blank(white) png instead of what I expected

1). What am I doing wrong?

2). Is there any other possible ways to get the image representation of webpage(Using swift)?

Thank you!


Solution

  • Latest Update:

    Now you can take screenshot of WKWebView just like WebView.

    Apple added new method for both iOS and macOS,

    func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, 
    completionHandler: @escaping (NSImage?, Error?) -> Void)
    

    But its still in beta.


    You can't take a screenshot of WKWebView. It always returns a blank image. Even if you try to include WKWebView inside another NSView and take a screenshot, it will give you blank image in place of WKWebView.

    You should use WebView instead of WKWebView for your purpose. Check this question.

    If you are ok with using private frameworks(apple doesn't allow your app in its store), check this GitHub. Its written in Obj-C. I don't know Obj-C so I can't explain what's happening in that code. But it claims to do the work.

    Your best approach is to use WebView and use your mentioned extension data() on the WebView.

    Just a question: Why don't you use phantomJS?

    PS. Sorry for the late reply. I didn't see your e-mail.