4 回答

TA貢獻1876條經驗 獲得超7個贊
讓我解釋一下當前代碼的功能以及如何修改它以捕獲全屏屏幕,而不是僅僅把答案扔在那里。
UIGraphicsBeginImageContext(view.frame.size)
這行代碼將創建一個新的圖片上下文,其大小與相同view。這里要摘錄的主要內容是新圖像上下文的大小與相同view。除非您要捕獲應用程序的低分辨率(非視網膜)版本,否則可能應該使用它UIGraphicsBeginImageContextWithOptions。然后,您可以通過0.0獲得與設備主屏幕相同的比例因子。
view.layer.renderInContext(UIGraphicsGetCurrentContext())
這行代碼會將視圖的圖層渲染到當前的圖形上下文(即您剛剛創建的上下文)中。這里要view摘錄的主要內容是只有(及其子視圖)被繪制到圖像上下文中。
let image = UIGraphicsGetImageFromCurrentImageContext()
這行代碼根據繪制到圖形上下文中的內容創建一個UIImage對象。
UIGraphicsEndImageContext()
這行代碼結束了圖像上下文。它已經清理了(您創建了上下文,也應該將其刪除。
其結果是,其大小與相同的圖像view,用view和它的子視圖吸入到它。
如果要將所有內容繪制到圖像中,則應創建與屏幕大小相同的圖像,然后將屏幕上的所有內容繪制到圖像中。實際上,您可能只是在談論應用程序“鍵窗口”中的所有內容。由于UIWindow是的子類UIView,因此也可以將其繪制到圖像上下文中。

TA貢獻1943條經驗 獲得超7個贊
斯威夫特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
}
為Swift 2更新
您提供的代碼有效,但不允許您捕獲屏幕快照中的NavigationBar和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不會出現在最終圖像。

TA貢獻1842條經驗 獲得超13個贊
細節
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)
}
}
用法
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,快速3
適用于iOS 10x的版本1
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
}
}
適用于iOS 9x,10x的版本2
如果您嘗試在iOS 9x中使用版本1代碼, 則會出現錯誤: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
}
}
用法
let screenShot = UIApplication.shared.screenShot!

TA貢獻1813條經驗 獲得超2個贊
迅速UIImage擴展:
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)
}
}
用法:
let myImage: UIImage? = UIImage(view: myView)
- 4 回答
- 0 關注
- 832 瀏覽
添加回答
舉報