How to take UIWebView screenshot in Swift on iOS?

One of the more frequent questions on stack overflow is how to take a screenshot of a webView.

While working on our company’s app, I initially had to implement screenshot on UIWebView and recently had to port the code to use WKWebView and implement the same screenshot code. I initially started off to share code for wkwebview and uiwebview. But the post of UIWebView got so long that I decided to restrict this post to UIWebView full screenshot

For full screenshot in UIWebView

  1. Save the current frame of the uiwebview object
  2. Update frame to be same as uiwebView.scrollview height ( This step is necessary as you are taking a screenshot of the entire web Page content, including below the fold as well)
  3. Create a CGRect with ( height = uiwebview.scrollview.height , width = screen.width)

The next step is to generate a UIImage which contains the “snapshot” of the current state of the UIWebView. For this we need to draw the UIWebView’s snapshot into a graphics context , capture the screenshot and generate the UIImage object. For more details on graphics context, refer here

4. Call UIGraphicsBeginImageContext to create a new graphics context and to make it the default graphics context

5. Call function to render the webView.layer into the current graphics context

6. Call UIGraphicsGetImageFromCurrentContext to generate a UIImage object from the current context

7. Call UIGraphicsEndImageContext to uninitialize the  graphics context created in step 4

Below is the code to generate the uiwebview screenshot assuming you have the uiwebview object

Potential code modifications you might need to consider:

  1. renderInContext consumes a lot of memory ( potentially 150MB which can result in memory termination of the app) for rendering the entire webPage into the current graphics context. Refer to this link for potential work around. ( I personally find it hacky)
  2. You can play with the parameters to UIGraphicsBeginImageContextWithOptions depending on your requirement. Refer to this and this for more ideas
  3. If you want to take the screenshot of only visible portion of the UIWebView, the following modifications need to be made
    1. Ignore all changes to scrollView offset
    2. The webView frame is set to be of device’s height and width
    3. The size of the context also needs to be set to be same as the device’s screen size
  4. You can generate a JPG or PNG data from the UIImage  object using UIImageJPEGRepresentation and UIImagePNGRepresentation
  5. If your UIWebView can render any possible external website, test for different sites (use different technology) that render different content ( excel, pdf, ppt).
  6. Remember WKWebView is much more performant, albeit few features missing,  webView control . Make sure you analyze your requirements and see if you could take advantage of this control

Links

List of all the links referenced in this blog post

iOS Drawing Concepts

renderInContext consumes a lot of memory and eventually crashes

UIImageJPEGRepresentation

UIImagePNGRepresentation

UIGraphicsBeginImageContextWithOptions

WKWebView ( part of WebKit framework)

Captured screenshot is not of retina quality 

How to take UIWebView screenshot in Swift on iOS?

Leave a Reply

Your email address will not be published. Required fields are marked *