如何在后台线程上截取UIView的屏幕截图?

时间:2018-10-02 12:37:55

标签: ios swift uiview ios-multithreading

我正在使用的应用几乎在每个屏幕上都有google maps。为了节省内存,我在各处重复使用相同的Google地图视图。问题是,当您弹出viewController时,您可以看到地图所在的空白区域。要解决此问题,我先将其截屏并添加为背景,然后再删除地图。但是还有另一个问题,在iPhoneX上截图大约需要0.3秒(我想在旧款手机上更糟)。有什么方法可以在后台线程上获取UIView的屏幕截图?

3 个答案:

答案 0 :(得分:2)

我使用swift尝试了所有最新的快照方法。在后台,其他方法对我不起作用。但是以这种方式拍摄快照对我有用。

使用参数视图图层和视图边界创建扩展。

extension UIView {
    func asImageBackground(viewLayer: CALayer, viewBounds: CGRect) -> UIImage {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: viewBounds)
            return renderer.image { rendererContext in
                viewLayer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContext(viewBounds.size)
            viewLayer.render(in:UIGraphicsGetCurrentContext()!)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return UIImage(cgImage: image!.cgImage!)
        }
    }
}

用法

DispatchQueue.main.async {
                let layer = self.selectedView.layer
                let bounds = self.selectedView.bounds
                DispatchQueue.global(qos: .background).async {
                    let image = self.selectedView.asImageBackground(viewLayer: layer, viewBounds: bounds)
                }
            }

我们需要计算主线程中的图层和边界,然后其他操作将在后台线程中进行。它将提供流畅的用户体验,而不会出现UI延迟或中断。

答案 1 :(得分:1)

通过 UIKit 来自documentation

  

除非另有说明,否则仅从应用程序的主线程或主调度队列中使用UIKit类。此限制特别适用于从UIResponder派生的类,或涉及以任何方式操纵应用程序用户界面的类。

由于您使用的是UIKit方法,因此我不认为可以对后台线程的视图进行快照。

答案 2 :(得分:1)

实际上,有可能!但是首先在UIThread上,您需要获取如下信息:

CALayer* layer = view.layer;
CGRect frame = view.frame;

,然后更改为下面的backgroundthead使用代码以获取图像:

UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
[layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();