¿Cómo tomo una captura de pantalla de pantalla completa en Swift?

Encontré este código :

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) } 

¿Qué debo hacer para incluir todos los demás elementos, como la barra de navegación, en las capturas de pantalla?

En lugar de solo arrojar la respuesta, permítame explicarle qué hace su código actual y cómo modificarlo para capturar la pantalla completa.

 UIGraphicsBeginImageContext(view.frame.size) 

Esta línea de código crea un nuevo contexto de imagen con el mismo tamaño que la view . Lo más importante es que el nuevo contexto de imagen tiene el mismo tamaño que la view . A menos que desee capturar una versión de baja resolución (no retina) de su aplicación, probablemente debería usar UIGraphicsBeginImageContextWithOptions en UIGraphicsBeginImageContextWithOptions lugar. Luego puede pasar 0.0 para obtener el mismo factor de escala que la pantalla principal de los dispositivos.

 view.layer.renderInContext(UIGraphicsGetCurrentContext()) 

Esta línea de código representará la capa de la vista en el contexto de gráficos actual (que es el contexto que acaba de crear). Lo principal que debemos quitar aquí es que solo la view (y sus subvistas) se dibujan en el contexto de la imagen.

 let image = UIGraphicsGetImageFromCurrentImageContext() 

Esta línea de código crea un objeto UIImage a partir de lo que se ha dibujado en el contexto gráfico.

 UIGraphicsEndImageContext() 

Esta línea de código finaliza el contexto de la imagen. Es limpieza (usted creó el contexto y debería eliminarlo también).


El resultado es una imagen del mismo tamaño que la view , con la view y sus subvistas dibujadas en ella.

Si desea dibujar todo en la imagen, debe crear una imagen del tamaño de la pantalla y dibujar en ella todo lo que está en la pantalla. En la práctica, es probable que solo hable de todo en la “ventana clave” de su aplicación. Como UIWindow es una subclase de UIView , también se puede dibujar en un contexto de imagen.

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's 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 } 

Actualizado para Swift 2

El código que proporciona funciona pero no le permite capturar NavigationBar y StatusBar en su captura de pantalla. Si desea tomar una captura de pantalla de su dispositivo que incluirá NavigationBar , debe usar el siguiente código:

 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) } 

Con este código:

  • La primera vez que inicie la aplicación y llame a este método, el dispositivo iOS le pedirá permiso para guardar su imagen en el rollo de la cámara.
  • El resultado de este código será una imagen .JPG.
  • StatusBar no aparecerá en la imagen final.

Ejemplo de Swift 3:

 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 } 

Detalles

Xcode 9.3, Swift 4.1

Probado en iOS: 9, 10, 11

Solución

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

Uso

  imageView.image = UIApplication.shared.screenShot 

Detalles

Xcode 8.2.1, veloz 3

Versión 1 para 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 } } 

Versión 2 para iOS 9x, 10x

Si intenta usar el código de la Versión 1 en iOS 9x , tendrá un error: CGImageCreateWithImageProvider: proveedor de imágenes no válido: 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 } } 

Uso

 let screenShot = UIApplication.shared.screenShot! 

Para mayor facilidad, agregaría una extensión en su propio archivo

 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 } } 

llama a la extensión de la siguiente manera …

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

Del mismo modo, uno podría extender UIView para capturar una imagen de eso ….

La forma recomendada de crear un contexto en iOS 10 es usar 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 } } 

Yo uso este método:

 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; } 

Captura todas las barras excepto la de estado, y no solicita permiso para guardar imágenes en el rollo de la cámara.

¡Espero eso ayude!

  // 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 } 

Swift 3 Extension para 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 } }] 

Esto es similar, con suerte, ayuda a alguien en el futuro.

 self.view.image() //returns UIImage 

Aquí hay una solución de Swift 3

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

view.snapshotView (afterScreenUpdates: true)