web-dev-qa-db-de.com

Wie mache ich einen Vollbild-Screenshot in Swift?

Ich habe diesen Code gefunden:

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

Was muss ich tun, um alle anderen Elemente wie die Navigationsleiste in die Screenshots zu integrieren?

56
Pietro La Spada

Lassen Sie mich nicht einfach nur die Antwort hinauswerfen, sondern erklären, was Ihr aktueller Code macht und wie Sie ihn modifizieren können, um den gesamten Bildschirm zu erfassen.

UIGraphicsBeginImageContext(view.frame.size)

Diese Codezeile erstellt einen neuen Bildkontext mit derselben Größe wie view. Die Hauptsache, die Sie mitnehmen sollten, ist, dass der neue Bildkontext die gleiche Größe wie view hat. Wenn Sie keine Version mit niedriger Auflösung (ohne Retina) Ihrer Anwendung erfassen möchten, sollten Sie stattdessen UIGraphicsBeginImageContextWithOptions verwenden. Dann können Sie 0.0 übergeben, um denselben Skalierungsfaktor wie der Hauptbildschirm des Geräts zu erhalten. 

view.layer.renderInContext(UIGraphicsGetCurrentContext())

Diese Codezeile rendert den Layer der Ansicht in den aktuellen Grafikkontext (den gerade erstellten Kontext). Die Hauptsache, die Sie hier mitnehmen sollten, ist, dass nur view (und ihre Unteransichten) in den Bildkontext gezogen werden.

let image = UIGraphicsGetImageFromCurrentImageContext()

Diese Codezeile erstellt ein UIImage-Objekt aus den in den Grafikkontext gezeichneten Elementen. 

UIGraphicsEndImageContext()

Diese Codezeile beendet den Bildkontext. Es ist aufgeräumt (Sie haben den Kontext erstellt und sollten ihn auch entfernen. 


Das Ergebnis ist ein Bild, das die gleiche Größe wie view hat, wobei view und die dazugehörigen Unteransichten gezeichnet werden.

Wenn Sie alles in das Bild einzeichnen möchten, sollten Sie ein Bild in der Größe des Bildschirms erstellen und alles auf dem Bildschirm zeichnen. In der Praxis sprechen Sie wahrscheinlich nur über das "Schlüsselfenster" Ihrer Anwendung. Da UIWindow eine Unterklasse von UIView ist, kann sie auch in einen Bildkontext gezeichnet werden.

66

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
    }

Aktualisiert für Swift 2

Der von Ihnen bereitgestellte Code funktioniert, aber Sie können nicht die NavigationBar und die StatusBar in Ihrem Screenshot erfassen. Wenn Sie einen Screenshot Ihres Geräts erstellen möchten, der die NavigationBar enthält, müssen Sie den folgenden Code verwenden:

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

Mit diesem Code:

  • Wenn Sie die App zum ersten Mal starten und diese Methode aufrufen, werden Sie vom iOS-Gerät nach der Berechtigung gefragt, Ihr Bild in der Kamerarolle zu speichern.
  • Das Ergebnis dieses Codes ist ein JPG-Bild.
  • Die StatusBar erscheint nicht im endgültigen Bild.
49
Imanou Petit

Swift 3 Beispiel:

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
}
21
Daniel Storm

Einzelheiten

Xcode 9.3, Swift 4.1

Getestet auf iOS: 9, 10, 11

Lösung

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

Verwendungszweck

 imageView.image = UIApplication.shared.screenShot

Einzelheiten

Xcode 8.2.1, Swift 3

Version 1 für 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 für iOS 9x, 10x

Wenn Sie versuchen, Version 1-Code in iOS 9x zu verwenden, erhalten Sie folgende Fehlermeldung: CGImageCreateWithImageProvider: ungültiger Bildanbieter: 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
    }
}

Verwendungszweck

let screenShot = UIApplication.shared.screenShot!
19

Der Einfachheit halber würde ich eine Erweiterung in die eigene Datei einfügen

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

rufen Sie die Erweiterung wie folgt an ...

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

let windowImage = window.capture()

Ebenso könnte man UIView erweitern, um ein Bild davon aufzunehmen. 

9
Damo

Die empfohlene Methode zum Erstellen eines Kontexts in iOS 10 ist die Verwendung von 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
neave

Ich verwende diese Methode:

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

Es erfasst alles außer der Statusleiste und fragt nicht nach der Erlaubnis, Bilder in der Kamerarolle zu speichern.

Ich hoffe es hilft!

3
diegomen

Swift 3 Erweiterung für 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
Gregg

Das ist ähnlich, hoffentlich hilft es jemandem in der Zukunft.

self.view.image() //returns UIImage

Hier ist eine Swift 3-Lösung

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

1
Ryan G
  // 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
Rex

Meine Version erfasst auch eine Tastatur. Schnell 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

view.snapshotView (afterScreenUpdates: true)

0
Adam Smaka

So mache ich es 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()

jetzt wird der Screenshot vom Typ UIImage sein

Swift 4 oder höher.

Für Nebenstellen und Anrufe von UIView, die Sie erfassen.

Erklärung

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

    }
}

Verwendungszweck

var m_image = UIImage()

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

// m_Capture_View ist ein UIView-Typ

0