我找到this code:
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)
}
我需要做些什么才能将所有其他元素(例如导航栏)添加到屏幕截图中?
答案 0 :(得分:69)
让我解释一下当前代码的作用以及如何修改它以捕获全屏幕,而不仅仅是将答案抛出那里。
UIGraphicsBeginImageContext(view.frame.size)
此代码行创建一个与view
大小相同的新图像上下文。这里要取消的主要内容是新图像上下文与view
的大小相同。除非您想要捕获应用程序的低分辨率(非视网膜)版本,否则您可能应该使用UIGraphicsBeginImageContextWithOptions
。然后,您可以传递0.0
以获得与设备主屏幕相同的比例因子。
view.layer.renderInContext(UIGraphicsGetCurrentContext())
这行代码会将视图层渲染到当前图形上下文(这是您刚刚创建的上下文)。这里要带走的主要事情是只有view
(及其子视图)被绘制到图像上下文中。
let image = UIGraphicsGetImageFromCurrentImageContext()
这行代码根据绘制到图形上下文中的内容创建UIImage对象。
UIGraphicsEndImageContext()
这行代码结束了图像上下文。它已经清理了(你创建了上下文,也应该删除它。
结果是与view
大小相同的图片,其中view
及其子视图被吸引到其中。
如果要将所有内容绘制到图像中,则应创建一个与屏幕大小相同的图像,并将屏幕上的所有内容绘制到其中。在实践中,您可能只是在关键窗口中讨论所有内容"你的申请。由于UIWindow
是UIView
的子类,因此也可以将其绘制到图像上下文中。
答案 1 :(得分:51)
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
}
更新了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)
}
使用此代码:
StatusBar
不会出现在最终图片中。答案 2 :(得分:21)
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
}
答案 3 :(得分:20)
在iOS上测试:9,10,11,12
imageView.image = UIApplication.shared.screenShot
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
}
}
Xcode 8.2.1,swift 3
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
}
}
如果您尝试在iOS 9x中使用版本1代码,则会出现错误: CGImageCreateWithImageProvider:无效的图像提供程序:NULL。
let screenShot = UIApplication.shared.screenShot!
{{1}}
答案 4 :(得分:9)
为方便起见,我会在其自己的文件中添加一个扩展名
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来捕捉那个......的图像。
答案 5 :(得分:4)
在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
}
}
答案 6 :(得分:3)
我使用这种方法:
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;
}
它捕获除状态栏以外的所有内容,并且它不会要求允许在相机胶卷中保存图像。
希望它有所帮助!
答案 7 :(得分:2)
快捷键5
如果您只需要在那一瞬间获得屏幕的真实快照(带有键盘和状态栏):
snap
UIView
是view.addSubview(snap)
,其边框自动设置为屏幕的边界。现在将其添加到视图控制器的视图中将为您提供显示为冻结状态的UI:
func getAllWiFiNameList() -> String? {
var ssid: String?
if let interfaces = CNCopySupportedInterfaces() as NSArray? {
for interface in interfaces {
if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? {
ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
break
}
}
}
return ssid
}
不需要扩展和所有不必要的东西-两行代码就足够了。
答案 8 :(得分:1)
// 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 :(得分:1)
UIWindow的Swift 3扩展程序
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 :(得分:1)
这是类似的,希望将来可以帮助某人。
self.view.image() //returns UIImage
这是一个Swift 3解决方案
https://gist.github.com/nitrag/b3117a4b6b8e89fdbc12b98029cf98f8
答案 11 :(得分:0)
view.snapshotView(afterScreenUpdates:true)
答案 12 :(得分:0)
我的版本还捕获了一个键盘。雨燕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 :(得分:0)
Swift 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 :(得分:0)
这就是我在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
答案 15 :(得分:0)
与 Swift 5 和 iOS 13
一起使用对于那些希望为函数提供快速答案以将 view 的屏幕截图作为UIImage返回的人:
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
}
我通过考虑问题中的代码并遵循DavidRönnqvist的建议(感谢您的解释)并进行了一些调整来拼凑出这个答案。
要包括导航栏和其他附加功能,请从窗口而不是 view 调用此方法。
我只需要一个函数来获取视图的屏幕截图,所以我希望这可以帮助寻找相同视图的任何人
答案 16 :(得分:0)
此代码是最新版本-100%有效
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!;
}
答案 17 :(得分:0)
Swift 5
捕获整个屏幕(减去状态栏)而不会在较新的设备(如 iPhone 12 Pro)上崩溃。
extension UIApplication {
func getScreenshot() -> UIImage? {
guard let window = keyWindow else { return nil }
let bounds = UIScreen.main.bounds
UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)
window.drawHierarchy(in: bounds, afterScreenUpdates: true)
guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
UIGraphicsEndImageContext()
return image
}
}
之前使用 UIApplication.shared.keyWindow?.layer.render(in: context)
的解决方案会导致某些设备(如 iPhone 12 Pro)出现内存崩溃。