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 aufzunehmen?
ios
swift
uiimage
screenshot
Pietro La Spada
quelle
quelle
Antworten:
Lassen Sie mich erklären, was Ihr aktueller Code bewirkt und wie Sie ihn ändern können, um den gesamten Bildschirm zu erfassen, anstatt nur die Antwort zu veröffentlichen.
UIGraphicsBeginImageContext(view.frame.size)
Diese Codezeile erstellt einen neuen Bildkontext mit der gleichen Größe wie
view
. Die Hauptsache, die Sie hier mitnehmen sollten, ist, dass der neue Bildkontext dieselbe Größe hat wieview
. Sofern Sie keine Version Ihrer Anwendung mit niedriger Auflösung (ohne Netzhaut) erfassen möchten, sollten Sie wahrscheinlichUIGraphicsBeginImageContextWithOptions
stattdessen verwenden. Dann können Sie übergeben0.0
, um den gleichen Skalierungsfaktor wie auf dem Hauptbildschirm des Geräts zu erhalten.view.layer.renderInContext(UIGraphicsGetCurrentContext())
Diese Codezeile rendert die Ebene der Ansicht in den aktuellen Grafikkontext (den gerade erstellten Kontext). Die Hauptsache, die hier weggenommen werden muss, ist, dass nur
view
(und ihre Unteransichten) in den Bildkontext gezogen werden.let image = UIGraphicsGetImageFromCurrentImageContext()
Diese Codezeile erstellt ein UIImage-Objekt aus dem, was in den Grafikkontext gezeichnet wurde.
UIGraphicsEndImageContext()
Diese Codezeile beendet den Bildkontext. Es wird bereinigt (Sie haben den Kontext erstellt und sollten ihn ebenfalls entfernen.
Das Ergebnis ist ein Bild mit der gleichen Größe wie
view
mitview
und den darin gezeichneten Unteransichten.Wenn Sie alles in das Bild zeichnen möchten, sollten Sie ein Bild erstellen, das der Größe des Bildschirms entspricht, und alles, was auf dem Bildschirm angezeigt wird, in das Bild zeichnen. In der Praxis sprechen Sie wahrscheinlich nur über alles im "Schlüsselfenster" Ihrer Anwendung. Da
UIWindow
es sich um eine Unterklasse von handeltUIView
, kann sie auch in einen Bildkontext gezeichnet werden.quelle
UIGraphicsBeginImageContext
Sie feststellen, dass sieUIGraphicsBeginImageContextWithOptions
mit einem Skalierungsfaktor von aufruft1.0
. Wenn Sie die Dokumentation lesen, erfahren Sie, dass Sie den Skalierungsfaktor so einstellen können0.0
, dass er mit Ihrem Hauptbildschirm übereinstimmt.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 das
NavigationBar
und dasStatusBar
in Ihrem Screenshot nicht erfassen . Wenn Sie einen Screenshot Ihres GerätsNavigationBar
erstellen möchten, der Folgendes 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:
StatusBar
wird im endgültigen Bild nicht angezeigt.quelle
Einzelheiten
Getestet unter iOS: 9, 10, 11, 12, 13
Lösung
import UIKit extension UIApplication { func getKeyWindow() -> UIWindow? { if #available(iOS 13, *) { return windows.first { $0.isKeyWindow } } else { return keyWindow } } func makeSnapshot() -> UIImage? { return getKeyWindow()?.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) } }
Verwendung
imageView.image = UIApplication.shared.makeSnapshot() // or imageView.image = view.makeSnapshot() // or imageView.image = view.layer.makeSnapshot() // or imageView.image = UIImage(snapshotOf: view)
Alte Lösung
Xcode 8.2.1, schnell 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
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 } }
Verwendung
let screenShot = UIApplication.shared.screenShot!
quelle
Schnelle
UIImage
Erweiterung:extension UIImage { convenience init?(view: UIView?) { guard let view: UIView = view else { return nil } UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale) guard let context: CGContext = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext() return nil } view.layer.render(in: context) let contextImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() guard let image: UIImage = contextImage, let pngData: Data = image.pngData() else { return nil } self.init(data: pngData) } }
Verwendung:
let myImage: UIImage? = UIImage(view: myView)
quelle
Der Einfachheit halber würde ich eine Erweiterung in eine 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 Nebenstelle wie folgt auf ...
let window: UIWindow! = UIApplication.sharedApplication().keyWindow let windowImage = window.capture()
Ebenso könnte man UIView erweitern, um ein Bild davon aufzunehmen ....
quelle
Die empfohlene Methode zum Erstellen eines Kontexts in iOS 10 ist die Verwendung
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 } }
quelle
Ich benutze 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 werden alle außer der Statusleiste erfasst und es wird nicht um Erlaubnis zum Speichern von Bildern in der Kamerarolle gebeten.
Ich hoffe es hilft!
quelle
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 } }]
quelle
So mache ich das 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
quelle
Funktioniert mit Swift 5 und iOS 13
Für alle, die eine schnelle Antwort auf eine Funktion suchen, um einen Screenshot der Ansicht als UIImage zurückzugeben:
func getScreenshot() -> UIImage? { //creates new image context with same size as view // UIGraphicsBeginImageContextWithOptions (scale=0.0) for high res capture UIGraphicsBeginImageContextWithOptions(view.frame.size, true, 0.0) // renders the view's layer into the current graphics context if let context = UIGraphicsGetCurrentContext() { view.layer.render(in: context) } // creates UIImage from what was drawn into graphics context let screenshot: UIImage? = UIGraphicsGetImageFromCurrentImageContext() // clean up newly created context and return screenshot UIGraphicsEndImageContext() return screenshot }
Ich habe diese Antwort zusammengesetzt, indem ich den Code in der Frage übernommen und den Vorschlägen von David Rönnqvist gefolgt bin (danke für die Erklärung), mit einigen Verbesserungen.
Rufen Sie diese Methode außerhalb des Fensters anstelle der Ansicht auf, um die Navigationsleiste und andere Extras einzuschließen .
Ich brauchte einfach eine Funktion, um die Bildschirmaufnahme der Ansicht zu erhalten, also hoffe ich, dass dies jedem hilft, der nach dem gleichen sucht
quelle
// 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 }
quelle
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
quelle
Dieser Code ist die neueste Version - 100% funktioniert
func getScreenshoot() -> UIImage { var window: UIWindow? = UIApplication.shared.keyWindow window = UIApplication.shared.windows[0] as? UIWindow UIGraphicsBeginImageContextWithOptions(window!.frame.size, window!.isOpaque, 0.0) window!.layer.render(in: UIGraphicsGetCurrentContext()!) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image!; }
quelle
Swift 5
Wenn Sie in diesem Moment nur einen echten Schnappschuss des Bildschirms (mit Tastatur und Statusleiste) benötigen:
let snap = UIScreen.main.snapshotView(afterScreenUpdates: false)
snap
ist einUIView
mit einem Rahmen, der automatisch an die Grenzen des Bildschirms gesetzt wird. Wenn Sie es der Ansicht eines Ansichts-Controllers hinzufügen, erhalten Sie jetzt eine Benutzeroberfläche, die eingefroren erscheint:Keine Notwendigkeit für Erweiterungen und all das unnötige Zeug - 2 Codezeilen sind genug.
quelle
quelle
Meine Version erfasst auch eine Tastatur. 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 } }
quelle
Swift 4 oder höher.
Für die Erweiterung und den Anruf 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 } }
Verwendung
var m_image = UIImage() if let tempCaptureImg = self.m_Capture_View.viewCapture() { viewController.m_image = tempCaptureImg }
// m_Capture_View ist ein UIView-Typ
quelle