我正在使用此代码捕获屏幕截图并将其保存到相册中。
-(void)TakeScreenshotAndSaveToPhotoAlbum
{
UIWindow *window = [UIApplication sharedApplication].keyWindow;
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
UIGraphicsBeginImageContextWithOptions(window.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(window.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}
但问题是无论何时保存屏幕截图,我都看不到iPhone的状态栏。相反,底部会出现一个空白区域。如下图所示:
我做错了什么?
答案 0 :(得分:18)
状态栏实际上位于自己的UIWindow中,在您的代码中,您只渲染viewcontroller的视图,而不包含此视图。
“官方”屏幕截图方法是here,但现在似乎已被Apple删除,可能是因为它已过时。
在iOS 7下,UIScreen
上有一个新方法,用于获取包含整个屏幕内容的视图:
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates
这将为您提供一个视图,然后您可以在屏幕上操作各种视觉效果。
如果要将视图层次结构绘制到上下文中,则需要遍历应用程序的窗口([[UIApplication sharedApplication] windows]
)并在每个窗口上调用此方法:
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates
你可能能够结合上述两种方法并拍摄快照视图,然后在快照上使用上述方法绘制它。
答案 1 :(得分:7)
建议的“官方”屏幕截图方法不捕获状态栏(它不在应用程序的Windows列表中)。在iOS 5上测试过。
我相信,这是出于安全原因,但在文档中没有提到它。
我建议两个选择:
答案 2 :(得分:6)
这是我的代码,用于截取屏幕截图并将其存储为NSData(在IBAction中)。使用sotred NSData,您可以共享或发送电子邮件或任何想要做的事情
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen])
{
// -renderInContext: renders in the coordinate space of the layer,
// so we must first apply the layer's geometry to the graphics context
CGContextSaveGState(context);
// Center the context around the window's anchor point
CGContextTranslateCTM(context, [window center].x, [window center].y);
// Apply the window's transform about the anchor point
CGContextConcatCTM(context, [window transform]);
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
// Render the layer hierarchy to the current context
[[window layer] renderInContext:context];
// Restore the context
CGContextRestoreGState(context);
}
}
// Retrieve the screenshot image
UIImage *imageForEmail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageDataForEmail = UIImageJPEGRepresentation(imageForEmail, 1.0);
答案 3 :(得分:1)
function error(value) {
if (console) {
console.error(value)
}
}
的上述问题的答案已经写在那里,以下是上述问题的Objective-C
版本答案。
适用于Swift 3 +
截取屏幕截图,然后使用它在某处显示或通过网络发送。
Swift
使用上述截图
让我们在UIImageView上显示屏幕截图
extension UIImage {
class var screenShot: UIImage? {
let imageSize = UIScreen.main.bounds.size as CGSize;
UIGraphicsBeginImageContextWithOptions(imageSize, false, 0)
guard let context = UIGraphicsGetCurrentContext() else {return nil}
for obj : AnyObject in UIApplication.shared.windows {
if let window = obj as? UIWindow {
if window.responds(to: #selector(getter: UIWindow.screen)) || window.screen == UIScreen.main {
// so we must first apply the layer's geometry to the graphics context
context.saveGState();
// Center the context around the window's anchor point
context.translateBy(x: window.center.x, y: window.center
.y);
// Apply the window's transform about the anchor point
context.concatenate(window.transform);
// Offset by the portion of the bounds left of and above the anchor point
context.translateBy(x: -window.bounds.size.width * window.layer.anchorPoint.x,
y: -window.bounds.size.height * window.layer.anchorPoint.y);
// Render the layer hierarchy to the current context
window.layer.render(in: context)
// Restore the context
context.restoreGState();
}
}
}
guard let image = UIGraphicsGetImageFromCurrentImageContext() else {return nil}
return image
}
}
获取图像数据以通过网络保存/发送
yourImageView = UIImage.screenShot
答案 4 :(得分:1)
下面的代码(以及其他访问方式)现在将使应用程序崩溃并显示一条消息:
在UIApplication上名为-statusBar或-statusBarWindow的应用程序:必须更改此代码,因为不再有状态栏或状态栏窗口。而是在窗口场景上使用statusBarManager对象。
窗口场景和statusBarManager确实仅使我们能够访问框架-如果仍然可行,我不知道怎么做。
以下内容适用于我,并且介绍了用于捕获程序化屏幕截图的所有方法后,这是最快的也是推荐的iOS 10之后Apple推荐的方式
let screenshotSize = CGSize(width: UIScreen.main.bounds.width * 0.6, height: UIScreen.main.bounds.height * 0.6)
let renderer = UIGraphicsImageRenderer(size: screenshotSize)
let statusBar = UIApplication.shared.value(forKey: "statusBarWindow") as? UIWindow
let screenshot = renderer.image { _ in
UIApplication.shared.keyWindow?.drawHierarchy(in: CGRect(origin: .zero, size: screenshotSize), afterScreenUpdates: true)
statusBar?.drawHierarchy(in: CGRect(origin: .zero, size: screenshotSize), afterScreenUpdates: true)
}
您不必缩小屏幕截图的大小(如果需要,可以直接使用UIScreen.main.bounds
)
答案 5 :(得分:0)
以下适用于我,捕获状态栏正常(iOS 9,Swift)
let screen = UIScreen.mainScreen()
let snapshotView = screen.snapshotViewAfterScreenUpdates(true)
UIGraphicsBeginImageContextWithOptions(snapshotView.bounds.size, true, 0)
snapshotView.drawViewHierarchyInRect(snapshotView.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
答案 6 :(得分:0)
捕获iPhone的全屏,使用KVC获取状态栏:
if let snapView = window.snapshotView(afterScreenUpdates: false) {
if let statusBarSnapView = (UIApplication.shared.value(forKey: "statusBar") as? UIView)?.snapshotView(afterScreenUpdates: false) {
snapView.addSubview(statusBarSnapView)
}
UIGraphicsBeginImageContextWithOptions(snapView.bounds.size, true, 0)
snapView.drawHierarchy(in: snapView.bounds, afterScreenUpdates: true)
let snapImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}