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?
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.
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:
StatusBar
erscheint nicht im endgültigen Bild.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
}
Xcode 9.3, Swift 4.1
Getestet auf 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
}
}
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
}
}
let screenShot = UIApplication.shared.screenShot!
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.
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
}
}
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!
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
}
}]
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
// 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
}
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
}
}
view.snapshotView (afterScreenUpdates: true)
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