How to take screenshot of a UIView in swift?
Asked Answered
W

7

43

I have a UIView named overView:

overView.frame = CGRectMake(self.view.frame.width/25, self.view.frame.height/25, self.view.frame.width/1.3, self.view.frame.height/1.2)

I want to take a screenshot of this view only and not my entire screen. And make the screenshot of size:

 (CGSizeMake(2480,3508 )

Here is my code:

UIGraphicsBeginImageContextWithOptions(CGSizeMake(2480,3508 ), false, 0);
self.view.drawViewHierarchyInRect(CGRectMake(-self.view.frame.width/25, -self.view.frame.height/25,2480,3508), afterScreenUpdates: true)
var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext()

The screenshot is of the required size however it takes the screenshot of the entire view instead of just "overView".

Wheeled answered 23/7, 2015 at 8:37 Comment(2)
possible duplicate of How Do I Take a Screen Shot of a UIView?Uxmal
It is possible to use XCUITest to take screenshots of elements as wellMedan
L
72

For drawing of one view, just use this:

    // Begin context
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.mainScreen().scale)

    // Draw view in that context
    drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)

    // And finally, get image
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

If you want to use it multiple times, probably extension would do the job:

//Swift4

extension UIView {

    func takeScreenshot() -> UIImage {

        // Begin context
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)

        // Draw view in that context
        drawHierarchy(in: self.bounds, afterScreenUpdates: true)

        // And finally, get image
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        if (image != nil)
        {
            return image!
        }
        return UIImage()
    }
}

//Old Swift

extension UIView {

    func takeScreenshot() -> UIImage {

        // Begin context
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.mainScreen().scale)

        // Draw view in that context
        drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)

        // And finally, get image
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image
    }
}

To explain what those parameters do:

UIGraphicsBeginImageContextWithOptions() creates a temporary rendering context into which the original is drawn. The first argument, size, is the target size of the scaled image. The second argument, isOpaque is used to determine whether an alpha channel is rendered. Setting this to false for images without transparency (i.e. an alpha channel) may result in an image with a pink hue. The third argument scale is the display scale factor. When set to 0.0, the scale factor of the main screen is used, which for Retina displays is 2.0 or higher (3.0 on the iPhone 6 Plus).

More about it here http://nshipster.com/image-resizing/

As for the draw call, Apple Docs explains it to detail here and here

Landeros answered 23/7, 2015 at 8:44 Comment(4)
hey thanks for a quick reply. Can you explain to me the parameters inside UIGraphicsBeginImageContextWithOptions and drawViewHierarchyInRect ?Wheeled
I've edited my answer to cover explanation + added some more linksLanderos
Hi, I have a problem with UIView in a UitableViewCell. the bottom is cut. Any suggestions??Bondsman
you could use return image ?? UIImage() instead of the if block with force-unwrapping.Ftlb
D
26

swift 4 and iOS 10+

extension UIView {

  func screenshot() -> UIImage {
    return UIGraphicsImageRenderer(size: bounds.size).image { _ in
      drawHierarchy(in: CGRect(origin: .zero, size: bounds.size), afterScreenUpdates: true)
    }
  }

}
Danie answered 20/9, 2017 at 11:4 Comment(0)
V
16

An alternative for Alessandro's answer, a bit more brief and Swift style:

extension UIView {

    var snapshot: UIImage {
        return UIGraphicsImageRenderer(size: bounds.size).image { _ in
            drawHierarchy(in: bounds, afterScreenUpdates: true)
        }
    }

}
Villarreal answered 17/10, 2018 at 14:19 Comment(0)
P
2

For Taking Screen Short Use This Solution. Hear I can Done How to Take Screen Short UIView with UIImage.

let img = self.captureScreen() // CaptureScreen Is A Function
        let someNSDate = NSDate()
        let myTimeStamp = someNSDate.timeIntervalSince1970
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentsDirectory = paths[0]

if let data = UIImageJPEGRepresentation(img, 0.8)
{
    let filename = documentsDirectory.appendingPathComponent("Img_\(myTimeStamp).jpeg")
    SavedImage_Ary.insert("Img_\(myTimeStamp).jpeg", at: 0) // SavedImage Is A NSMutableArray Where You Can Store your Image
    //print(SavedImage_Ary)
    try? data.write(to: filename)
    UserDefaults.standard.setValue(SavedImage_Ary, forKey: "Saved_Image")
    Save_Img = true
    //            self.dismiss(animated: true, completion: nil)
    Select_Flag = "textdata"
    let vc = self.storyboard?.instantiateViewController(withIdentifier: "photovc") as! UINavigationController
    self.present(vc, animated: true, completion: nil)
}


// MARK : Function

func captureScreen() -> UIImage
{

    UIGraphicsBeginImageContextWithOptions(Capture_View.frame.size, false, 0);
    Capture_View.drawHierarchy(in: Capture_View.bounds, afterScreenUpdates: true)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
}
Performative answered 6/7, 2018 at 2:34 Comment(0)
K
1
func screenShotMethod()->UIImage
    {
        let layer = self.view.layer
        let scale = UIScreen.main.scale
        UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);

        layer.render(in: UIGraphicsGetCurrentContext()!)
        let screenshot = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return screenshot!
    }
Karlenekarlens answered 28/12, 2018 at 9:47 Comment(0)
S
0

Swift 4.x and iOS 10+ with fallback solution:

extension UIView {
    func screenshot() -> UIImage {
        if #available(iOS 10.0, *) {
            return UIGraphicsImageRenderer(size: bounds.size).image { _ in
                drawHierarchy(in: CGRect(origin: .zero, size: bounds.size), afterScreenUpdates: true)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
            drawHierarchy(in: self.bounds, afterScreenUpdates: true)
            let image = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
            UIGraphicsEndImageContext()
            return image
        }
    }
}
Spectrum answered 18/9, 2018 at 5:48 Comment(0)
A
0

If you don't specifically need a UIImage but a UIView is fine, you can just use :

let snapshotView = yourView.snapshotView(afterScreenUpdates: true)

https://developer.apple.com/documentation/uikit/uiview/1622531-snapshotview

Afore answered 4/8, 2023 at 9:19 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.