如何拍摄未呈现的 UIView 的快照?

Posted

技术标签:

【中文标题】如何拍摄未呈现的 UIView 的快照?【英文标题】:How can I take a snapshot of a UIView that isn't rendered? 【发布时间】:2014-12-10 21:19:51 【问题描述】:

我用这种方法拍快照:

UIView *snapshotView = [someView snapshotAfterScreenUpdates:NO];

这给了我一个可以玩的 UIView。

但是,我需要它的 UIImage 而不是 UIView。

这是我用来将 UIView 转换为 UIImage 的方法:

- (UIImage *)snapshotOfView:(UIView *)view

    UIImage *snapshot;

    UIGraphicsBeginImageContext(view.frame.size);

    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    snapshot = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return snapshot;

不行,因为snapshotView没有渲染,所以snapshot是一个空白的UIImage。

显而易见的做法是直接对视图进行快照,而不是以 UIView 的形式进行快照,然后进行转换。

明显方法的问题是我使用的 WKWebView 有一个巨大的错误,不允许您截取屏幕截图。这是真的,我什至报告了这个错误,他们说他们正在努力修复它。

那么,如何在不渲染的情况下拍摄 snapshotView 的快照(UIImage)?

【问题讨论】:

@HussainShabbir - 不是骗子,不同的问题,不同的答案。另一个答案可能已经完成了这项工作,但这个答案与苹果当前的 api 是正确的。我知道它的效率要高得多(尽管我还没有测试过这种说法) 【参考方案1】:

drawViewHierarchyInRect 将为您工作。您可以直接在 WKWebView 上使用它。

this Apple Technical Q&A 上有一些有用的细节。我还谈到了here 以回答一个略有不同的问题。

我在 UIView 上的一个类别中使用它:

@implementation UIView (ImageSnapshot)
- (UIImage*)imageSnapshot 
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, 
                                    YES, self.contentScaleFactor);
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;

@end

我不知道你所说的“显而易见的方法”是什么意思 - 但我已经在 WKWebView 上对此进行了测试,并且它有效。

【讨论】:

你先生,太棒了! 你好@foundry,我很好奇你是否仍然认为这是一个适用于 ios 9.2 和 Xcode 7.2 (7C68) 的有效解决方案?我得到一张白色的图像。 @chinjazz:我刚刚尝试了 Xcode 7.2 (7C68) 与 ios9.2 和 ios8.4 的模拟器版本(用于比较).. 都可以正常工作 感谢您的确认!我发现在模拟器中,屏幕图像将第一次为 WKWebView 呈现,但不会在下一次加载时呈现(它是白色图像).. 可能是我的错误,但我会在设备上检查它一致性。 我发现使用 WKWebView 在 webView sucCubus Navigation 之后添加延迟效果更好......【参考方案2】:

由于接受者的回答对我不起作用(UIGraphicsGetImageFromCurrentImageContext() 一直返回nil),我为 iOS10+ 找到了different solution:

let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let image = renderer.image  _ in view.drawHierarchy(in: view.bounds, afterScreenUpdates: true) 

附:您可能需要在渲染之前调用updateConstraintsIfNeeded()layoutIfNeeded()

【讨论】:

以上是关于如何拍摄未呈现的 UIView 的快照?的主要内容,如果未能解决你的问题,请参考以下文章

在 ios7 中拍摄状态栏的快照

AWS RDS启用数据加密(创建时未启用情况下)

Vmware虚拟机怎么拍摄快照/vmware如何新建快照

JavaFX:如果节点边界设置为最大值,如何拍摄节点快照?

如何在 docker 中拍摄容器快照

虚拟机如何拍摄快照