Как сделать полный скриншот экрана в Swift?
Я нашел этот код:
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)
}
Что мне нужно сделать, чтобы получить все остальные элементы, такие как панель навигации, на скриншотах?
Ответы
Ответ 1
Вместо того, чтобы просто отбросить ответ, позвольте мне объяснить, что делает ваш текущий код и как его модифицировать, чтобы захватить весь экран.
UIGraphicsBeginImageContext(view.frame.size)
Эта строка кода создает новый контекст изображения с тем же размером, что и view
. Главное, что нужно убрать здесь, - это то, что новый контекст изображения имеет тот же размер, что и view
. Если вы не хотите захватить версию приложения с низким разрешением (без сетчатки), скорее всего, вы должны использовать UIGraphicsBeginImageContextWithOptions
. Затем вы можете передать 0.0
, чтобы получить тот же масштабный коэффициент, что и основной экран устройства.
view.layer.renderInContext(UIGraphicsGetCurrentContext())
Эта строка кода отобразит слой вида в текущий графический контекст (который является только что созданным контекстом). Главное, чтобы убрать здесь, состоит в том, что в контекст изображения втягиваются только view
(и его подпункты).
let image = UIGraphicsGetImageFromCurrentImageContext()
Эта строка кода создает объект UIImage из того, что было нарисовано в графическом контексте.
UIGraphicsEndImageContext()
Эта строка кода заканчивает контекст изображения. Он очищается (вы создали контекст и должны его удалить.
В результате получается изображение с таким же размером, как view
, с view
и его вложенными в него надписями.
Если вы хотите нарисовать все на изображении, тогда вы должны создать изображение, которое является размером экрана, и нарисовать все, что на экране. На практике вы, вероятно, просто говорите обо всем в "ключевом окне" вашего приложения. Поскольку UIWindow
является подклассом UIView
, его можно также вставить в контекст изображения.
Ответ 2
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 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
}
Обновлено для Swift 2
Предоставленный вами код работает, но не позволяет вам захватить StatusBar
NavigationBar
и StatusBar
на StatusBar
экрана. Если вы хотите сделать снимок экрана своего устройства с NavigationBar
, вы должны использовать следующий код:
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)
}
С этим кодом:
- Когда вы в первый раз запускаете приложение и вызываете этот метод, устройство iOS запросит у вас разрешение на сохранение вашего изображения в рулоне камеры.
- Результатом этого кода будет изображение .JPG.
-
StatusBar
не будет отображаться в конечном изображении.
Ответ 3
Подробнее
- Xcode 9.3, Swift 4.1
- Xcode 10.2 (10E125) и 11.0 (11A420a), Swift 5
Протестировано на iOS: 9, 10, 11, 12
Решение
import UIKit
extension UIApplication { func makeSnapshot() -> UIImage? { return keyWindow?.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)
}
}
Usage
Usage
imageView.image = UIApplication.shared.makeSnapshot()
// or
imageView.image = view.makeSnapshot()
// or
imageView.image = view.layer.makeSnapshot()
// or
imageView.image = UIImage(snapshotOf: view)
Старое решение
Xcode 8.2.1, swift 3
Версия 1 для 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
}
}
Версия 2 для iOS 9x, 10x
Если вы попытаетесь использовать код версии 1 в iOS 9x , у вас будет ошибка: CGImageCreateWithImageProvider: недопустимый поставщик изображений: 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
}
}
Usage
Usage
let screenShot = UIApplication.shared.screenShot!
Ответ 4
Пример 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
}
Ответ 5
Для удобства я бы добавил расширение в свой собственный файл
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
}
}
вызовите расширение следующим образом:
let window: UIWindow! = UIApplication.sharedApplication().keyWindow
let windowImage = window.capture()
Точно так же можно было расширить UIView, чтобы захватить изображение этого....
Ответ 6
Рекомендуемым способом создания контекста в iOS 10 является использование 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
}
}
Ответ 7
Я использую этот метод:
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;
}
Он фиксирует все, кроме строки состояния, и не запрашивает разрешения на сохранение изображений в кадре камеры.
Надеюсь, что это поможет!
Ответ 8
// 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
}
Ответ 9
Расширение Swift 3 для 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
}
}]
Ответ 10
Это похоже, надеюсь, это поможет кому-то в будущем.
self.view.image() //returns UIImage
Здесь решение Swift 3
https://gist.github.com/nitrag/b3117a4b6b8e89fdbc12b98029cf98f8
Ответ 11
view.snapshotView(afterScreenUpdates: true)
Ответ 12
Моя версия также захватить клавиатуру. 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
}
}
Ответ 13
Свифт 4 или выше.
Для расширения и вызова по UIView, что вы захватили.
декларация
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
}
}
использование
var m_image = UIImage()
if let tempCaptureImg = self.m_Capture_View.viewCapture() {
viewController.m_image = tempCaptureImg
}
//m_Capture_View - это тип UIView
Ответ 14
Вот как я это делаю в 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()
теперь скриншот будет иметь тип UIImage