Search code examples
ioswebviewuiwebviewwkwebview

Getting a snapshot of an area inside a WKWebView


I am trying to get a snapshot of a captcha present on a website so that I can ask my users to type that in a different UI. https://www.camsonline.com/InvestorServices/COL_ISAccountStatement.aspx I found the frame of the captcha by using

document.getElementById('captchImg').getBoundingClientRect();

But this frame is in reference to the webview and not the iOS window. I did try to convert using

webview.convert(CGRect(x: 685, y: 1063), to: self.view)

but that doesn't seem to do the trick. I just want the image from the snapshot of the captcha. What do I do? I have tried numerous answers on SO but nothing has helped so far.


Solution

  • I think you can save the cached image using base64 encoding, then convert it into UIImage anywhere you need. For example put it back into another UIImageView.

    This code example just load into self.imageView, you can do whatever you want with it.

       func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    
            let str = "var c = document.createElement('canvas'); var ctx = c.getContext('2d'); ctx.drawImage(document.getElementById('captchImg'), 100, 40); var value = c.toDataURL(); value.split(',')[1]; "
    
            self.webView.evaluateJavaScript(str) { (value, error) in
                 if error == nil {
                     if let img = value as? String {
                          self.imageView.image = self.base64ToImage(base64: img)
                     }
                 }
             }
        }
    
        func base64ToImage(base64: String) -> UIImage? {
            var img: UIImage = UIImage()
            if (!base64.isEmpty) {
                if let decodedData = NSData(base64Encoded: base64 , options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) {
                    if let decodedimage = UIImage(data: decodedData as Data) {
                        img = (decodedimage as UIImage?)!
                        return img
                    }
                }
            }
            return nil
        }