How to take a full screenshot in Swift?

I found this code :

func screenShotMethod() { //Create the UIImage UIGraphicsBeginImageContext(view.frame.size) view.layer.renderInContext(UIGraphicsGetCurrentContext()) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() //Save it to the camera roll UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) } 

What do I need to do to get all the other elements, such as the navigation bar, in the screenshots?

+63
ios swift uiimage screenshot
Aug 22 '14 at 2:03
source share
14 answers

Instead of just discarding the answer, let me explain what your current code does and how to modify it to capture the entire screen.

 UIGraphicsBeginImageContext(view.frame.size) 

This line of code creates a new image context with the same size as view . The main thing to remove here is that the new image context is the same size as the view . If you do not want to grab a low-resolution version of the application (without the retina), chances are you should use UIGraphicsBeginImageContextWithOptions . You can then transfer 0.0 to get the same scale factor as the main screen of the device.

 view.layer.renderInContext(UIGraphicsGetCurrentContext()) 

This line of code will map the view layer to the current graphics context (which is the context just created). The main thing to clean up here is that only view (and its sub-items) are drawn into the image context.

 let image = UIGraphicsGetImageFromCurrentImageContext() 

This line of code creates a UIImage object from what was drawn in the graphics context.

 UIGraphicsEndImageContext() 

This line of code ends the image context. It is cleared (you created the context and must delete it.




The result is an image with the same size as view , with view and its captions embedded in it.

If you want to draw everything on the image, then you must create an image that is the size of the screen and draw everything on the screen. In practice, you're probably just talking about everything in the "key window" of your application. Because UIWindow is a subclass of UIView , it can also be inserted into the image context.

+70
Aug 22 '14 at
source share

Swift 4

  /// Takes the screenshot of the screen and returns the corresponding image /// /// - Parameter shouldSave: Boolean flag asking if the image needs to be saved to user photo library. Default set to 'true' /// - Returns: (Optional)image captured as a screenshot open func takeScreenshot(_ shouldSave: Bool = true) -> UIImage? { var screenshotImage :UIImage? let layer = UIApplication.shared.keyWindow!.layer let scale = UIScreen.main.scale UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); guard let context = UIGraphicsGetCurrentContext() else {return nil} layer.render(in:context) screenshotImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() if let image = screenshotImage, shouldSave { UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) } return screenshotImage } 

Updated for Swift 2

The code you provided works, but does not allow you to capture the StatusBar NavigationBar and StatusBar on the StatusBar screen. If you want to take a screenshot of your device with the NavigationBar , you should use the following code:

 func screenShotMethod() { let layer = UIApplication.sharedApplication().keyWindow!.layer let scale = UIScreen.mainScreen().scale UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); layer.renderInContext(UIGraphicsGetCurrentContext()!) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() UIImageWriteToSavedPhotosAlbum(screenshot, nil, nil, nil) } 

With this code:

  • When you first launch the application and call this method, the iOS device will ask you for permission to save your image in the camera roll.
  • The result of this code will be a .JPG image.
  • StatusBar will not be displayed in the final image.
+56
Aug 23 '14 at 0:13
source share

the details

  • Xcode 9.3, Swift 4.1
  • Xcode 10.2 (10E125), Swift 5

Tested on iOS: 9, 10, 11, 12

Decision

 import UIKit extension UIApplication { func makeSnapshot() -> UIImage? { return keyWindow?.layer.makeSnapshot() } } extension CALayer { func makeSnapshot() -> UIImage? { let scale = UIScreen.main.scale UIGraphicsBeginImageContextWithOptions(frame.size, false, scale) defer { UIGraphicsEndImageContext() } guard let context = UIGraphicsGetCurrentContext() else { return nil } render(in: context) let screenshot = UIGraphicsGetImageFromCurrentImageContext() return screenshot } } extension UIView { func makeSnapshot() -> UIImage? { if #available(iOS 10.0, *) { let renderer = UIGraphicsImageRenderer(size: frame.size) return renderer.image { _ in drawHierarchy(in: bounds, afterScreenUpdates: true) } } else { return layer.makeSnapshot() } } } extension UIImage { convenience init?(snapshotOf view: UIView) { guard let image = view.makeSnapshot(), let cgImage = image.cgImage else { return nil } self.init(cgImage: cgImage, scale: image.scale, orientation: image.imageOrientation) } } 

using

 imageView.image = UIApplication.shared.makeSnapshot() // or imageView.image = view.makeSnapshot() // or imageView.image = view.layer.makeSnapshot() // or imageView.image = UIImage(snapshotOf: view) 



Old decision

Xcode 8.2.1, swift 3

Version 1 for iOS 10x

 import UIKit extension UIApplication { var screenShot: UIImage? { if let layer = keyWindow?.layer { let scale = UIScreen.main.scale UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); if let context = UIGraphicsGetCurrentContext() { layer.render(in: context) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } } return nil } } 

Version 2 for iOS 9x, 10x

If you try to use version 1 code in iOS 9x, you will get an error: CGImageCreateWithImageProvider: Invalid image provider: NULL.

 import UIKit extension UIApplication { var screenShot: UIImage? { if let rootViewController = keyWindow?.rootViewController { let scale = UIScreen.main.scale let bounds = rootViewController.view.bounds UIGraphicsBeginImageContextWithOptions(bounds.size, false, scale); if let _ = UIGraphicsGetCurrentContext() { rootViewController.view.drawHierarchy(in: bounds, afterScreenUpdates: true) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return screenshot } } return nil } } 

using

 let screenShot = UIApplication.shared.screenShot! 
+24
Dec 03 '16 at 22:09
source share

Swift 3 example:

 func captureScreen() -> UIImage? { guard let context = UIGraphicsGetCurrentContext() else { return .none } UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale) view.layer.render(in: context) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } 
+23
Sep 14 '16 at 21:11
source share

For convenience, I would add the extension to my own file

 import UIKit public extension UIWindow { func capture() -> UIImage { UIGraphicsBeginImageContextWithOptions(self.frame.size, self.opaque, UIScreen.mainScreen().scale) self.layer.renderInContext(UIGraphicsGetCurrentContext()!) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } } 

call the extension as follows:

 let window: UIWindow! = UIApplication.sharedApplication().keyWindow let windowImage = window.capture() 

In the same way, it was possible to extend the UIView to capture an image of this ....

+10
Apr 17 '15 at 14:39
source share

The recommended way to create context in iOS 10 is to use UIGraphicsImageRenderer .

 extension UIView { func capture() -> UIImage? { var image: UIImage? if #available(iOS 10.0, *) { let format = UIGraphicsImageRendererFormat() format.opaque = isOpaque let renderer = UIGraphicsImageRenderer(size: frame.size, format: format) image = renderer.image { context in drawHierarchy(in: frame, afterScreenUpdates: true) } } else { UIGraphicsBeginImageContextWithOptions(frame.size, isOpaque, UIScreen.main.scale) drawHierarchy(in: frame, afterScreenUpdates: true) image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() } return image } } 
+4
Apr 18 '17 at 8:40
source share

I am using this method:

 func captureScreen() -> UIImage { var window: UIWindow? = UIApplication.sharedApplication().keyWindow window = UIApplication.sharedApplication().windows[0] as? UIWindow UIGraphicsBeginImageContextWithOptions(window!.frame.size, window!.opaque, 0.0) window!.layer.renderInContext(UIGraphicsGetCurrentContext()) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image; } 

It captures everything except the status bar, and does not request permission to save images in the camera frame.

Hope this helps!

+3
Apr 12 '15 at 17:25
source share
  // Full Screen Shot function. Hope this will work well in swift. func screenShot() -> UIImage { UIGraphicsBeginImageContext(CGSizeMake(frame.size.width, frame.size.height)) var context:CGContextRef = UIGraphicsGetCurrentContext() self.view?.drawViewHierarchyInRect(frame, afterScreenUpdates: true) var screenShot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext(); return screenShot } 
+1
Jul 31 '15 at 7:22
source share

Swift 3 extension for UIWindow

 public extension UIWindow { func capture() -> UIImage? { UIGraphicsBeginImageContextWithOptions(self.frame.size, self.isOpaque, UIScreen.main.scale) self.layer.render(in: UIGraphicsGetCurrentContext()!) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } }] 
+1
Oct 25 '16 at 23:10
source share

It looks like I hope this helps someone in the future.

 self.view.image() //returns UIImage 

Here's the Swift 3 solution

https://gist.github.com/nitrag/b3117a4b6b8e89fdbc12b98029cf98f8

+1
Nov 21 '16 at 5:23
source share

view.snapshotView (afterScreenUpdates: true)

0
Sep 08 '16 at 15:20
source share

My version also capture the keyboard. Swift 4.2

 extension UIApplication { var screenshot: UIImage? { UIGraphicsBeginImageContextWithOptions(UIScreen.main.bounds.size, false, 0) guard let context = UIGraphicsGetCurrentContext() else { return nil } for window in windows { window.layer.render(in: context) } let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } } 
0
Oct 24 '18 at 10:47
source share

Swift 4 or higher.

To expand and call on the UIView that you captured.

declaration

 extension UIView { func viewCapture() -> UIImage? { UIGraphicsBeginImageContext(self.frame.size) guard let cgContext = UIGraphicsGetCurrentContext() else { print("Fail to get CGContext") return nil } self.layer.render(in: cgContext) guard let image = UIGraphicsGetImageFromCurrentImageContext() else { print("Fail to get Image from current image context") return nil } UIGraphicsEndImageContext() return image } } 

using

 var m_image = UIImage() if let tempCaptureImg = self.m_Capture_View.viewCapture() { viewController.m_image = tempCaptureImg } 

// m_Capture_View is a type of UIView

0
Mar 07 '19 at 12:15
source share

This is how I do it in Swift 4

 let layer = UIApplication.shared.keyWindow!.layer let scale = UIScreen.main.scale UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); layer.render(in: UIGraphicsGetCurrentContext()!) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() 

now the screenshot will be of type UIImage

0
May 11 '19 at 13:00
source share



All Articles