Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WKWebView Screenshots

Tags:

swift

I am trying to capture the image that the webview is displaying to the user, so I can some color analysis of the web page. When I try to get the image from it's parent, I am basically getting a white box, even though the page has rendered:

func makeImageSnapshot()-> (NSImage)
{


    let imgSize = self.view.bounds.size
    let bir = self.viewbitmapImageRepForCachingDisplayInRect(self.webView!.view.bounds)

    bir.size = imgSize
    self.webView.cacheDisplayInRect(self.view.bounds, toBitmapImageRep:bir)

    let image = NSImage(size:imgSize)
    image.addRepresentation(bir)
    self.image = image

    return image
}

func saveSnapshot()
{
    let imgRep = self.image!.representations[0]
    let data = imgRep.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: nil)
    data.writeToFile("/tmp/file.png", atomically: false)

}

It looks to me like I can't get access to the properties of the actual view (in this case the bounds) inside of the webView. When I try to access it, the compiler barfs:

/Users/josh/Canary/MacOsCanary/canary/canary/Modules/Overview/Overview.swift:55:37: '(NSView!, stringForToolTip: NSToolTipTag, point: NSPoint, userData: UnsafePointer<()>) -> String!' does not have a member named 'bounds'

My guess is that this is happening due to the extensions approach used by OS X and iOS. Any ideas, or should I just go back to using the legacy WebView?

like image 499
Josh Prismon Avatar asked Jul 13 '14 22:07

Josh Prismon


2 Answers

I realise the question was for Mac OS X, but I found this page whilst searching for an iOS solution. My answer below doesn't work on Mac OS X as the drawViewHierarchyInRect() API call is currently iOS only, but I put it here for reference for other iOS searchers.

This Stackoverflow answer solved it for me on iOS 8 with a WKWebView. That answer's sample code is in Objective-C but the Swift equivalent to go in a UIView sub-class or extension would be along the lines of the code below. The code ignores the return value of drawViewHierarchyInRect(), but you may want to pay attention to it.

func imageSnapshot() -> UIImage
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 0);
    self.drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true);
    let snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshotImage;
}
like image 97
user2067021 Avatar answered Oct 01 '22 01:10

user2067021


Swift 3

extension WKWebView {
    func screenshot() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 0);
        self.drawHierarchy(in: self.bounds, afterScreenUpdates: true);
        let snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return snapshotImage;
    }
}

Note: This solution only works on iOS.

like image 44
quemeful Avatar answered Oct 01 '22 02:10

quemeful