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条经验 获得超12个赞
细节
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 关注
- 786 浏览
添加回答
举报