J'ai trouvé ce 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)
}
Que dois-je faire pour obtenir tous les autres éléments, tels que la barre de navigation, dans les captures d'écran?
Au lieu de simplement donner la réponse, laissez-moi vous expliquer ce que fait votre code actuel et comment le modifier pour capturer tout l'écran.
UIGraphicsBeginImageContext(view.frame.size)
Cette ligne de code crée un nouveau contexte d'image de la même taille que view
. La principale chose à retenir ici est que le nouveau contexte d'image est la même taille que view
. À moins que vous ne souhaitiez capturer une version basse résolution (sans rétine) de votre application, vous devriez probablement utiliser UIGraphicsBeginImageContextWithOptions
à la place. Ensuite, vous pouvez passer 0.0
pour obtenir le même facteur d'échelle que l'écran principal du périphérique.
view.layer.renderInContext(UIGraphicsGetCurrentContext())
Cette ligne de code rendra la couche de la vue dans le contexte graphique actuel (qui est le contexte que vous venez de créer). La principale chose à retenir ici est que seules view
(et ses sous-vues) sont dessinées dans le contexte de l'image.
let image = UIGraphicsGetImageFromCurrentImageContext()
Cette ligne de code crée un objet UIImage à partir de ce qui a été dessiné dans le contexte graphique.
UIGraphicsEndImageContext()
Cette ligne de code termine le contexte de l'image. C'est le nettoyage (vous avez créé le contexte et vous devriez également le supprimer.
Le résultat est une image de la même taille que view
, avec view
et ses sous-vues dessinées.
Si vous souhaitez tout dessiner dans l'image, vous devez créer une image de la taille de l'écran et y dessiner tout ce qui y est affiché. En pratique, vous ne faites probablement que parler de tout ce qui se trouve dans la "fenêtre clé" de votre application. UIWindow
étant une sous-classe de UIView
, elle peut également être dessinée dans un contexte d'image.
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
}
Mise à jour pour Swift 2
Le code que vous fournissez fonctionne, mais ne vous permet pas de capturer les NavigationBar
et StatusBar
dans votre capture d'écran. Si vous voulez prendre une capture d'écran de votre appareil qui inclura la NavigationBar
, vous devez utiliser le code suivant:
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)
}
Avec ce code:
StatusBar
n'apparaîtra pas dans l'image finale.Exemple 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
}
Xcode 9.3, Swift 4.1
Testé sur iOS: 9, 10, 11
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
}
}
imageView.image = UIApplication.shared.screenShot
Xcode 8.2.1, Swift 3
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
}
}
Si vous essayez d'utiliser le code Version 1 dans iOS 9x vous aurez l'erreur suivante: CGImageCreateWithImageProvider: fournisseur d'image non valide: 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
}
}
let screenShot = UIApplication.shared.screenShot!
Pour plus de facilité, j'ajouterais une extension dans son propre fichier.
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
}
}
appelez l'extension comme suit ...
let window: UIWindow! = UIApplication.sharedApplication().keyWindow
let windowImage = window.capture()
De même, on pourrait utiliser UIView pour capturer une image de cela ....
La méthode recommandée pour créer un contexte dans iOS 10 consiste à utiliser 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
}
}
J'utilise cette méthode:
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;
}
Il capture tout sauf la barre d'état et ne demande pas la permission d'enregistrer des images dans le film.
J'espère que ça aide!
Extension Swift 3 pour 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
}
}]
C'est semblable, j'espère que cela aidera quelqu'un dans le futur.
self.view.image() //returns UIImage
Voici une solution Swift 3
https://Gist.github.com/nitrag/b3117a4b6b8e89fdbc12b98029cf98f8
// 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
}
Ma version capture également un clavier. 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
}
}
view.snapshotView (afterScreenUpdates: true)
Voici comment je le fais dans 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()
maintenant la capture d'écran sera de type UIImage
Swift 4 ou supérieur.
Pour extension et appel par UIView que vous avez capturé.
Déclaration
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
}
}
Utilisation
var m_image = UIImage()
if let tempCaptureImg = self.m_Capture_View.viewCapture() {
viewController.m_image = tempCaptureImg
}
// m_Capture_View est le type de UIView