可以把当前没有显示的uiview转成uiimage吗

Can you convert uiview that is not currently being displayed to uiimage

我发现了很多将 UIView 转换为 UIImage 的例子,一旦视图被布局等,它们就可以完美地工作。即使在我的视图控制器中有很多行,其中一些是净的但显示在屏幕上,我可以做转换。不幸的是,对于一些在 table 中太靠后的视图(因此还没有 "drawn"),进行转换会产生一个空白的 UIImage。

我试过调用 setNeedsDisplay 和 layoutIfNeeded,但它们不起作用。我什至尝试过自动滚动 table,但也许我没有以某种方式(使用线程)确保首先发生滚动,从而允许在转换发生之前更新视图。我怀疑这无法完成,因为我发现了各种问题,并且 none 找到了解决方案。或者,我可以只在 UIImage 中重绘我的整个视图,而不需要 UIView 吗?

来自 Paul Hudson 的网站

使用任何未显示在屏幕上的 UIView(比如 UITableview 中位于屏幕底部下方的一行。

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

您不必在 window/on-screen 中拥有视图即可将其呈现为图像。我在 PixelTest:

中完全做到了这一点
extension UIView {

    /// Creates an image from the view's contents, using its layer.
    ///
    /// - Returns: An image, or nil if an image couldn't be created.
    func image() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        context.saveGState()
        layer.render(in: context)
        context.restoreGState()
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
        UIGraphicsEndImageContext()
        return image
    }

}

如果要在屏幕上呈现,这会将视图的图层呈现为图像当前的样子。也就是说,如果视图尚未布局,那么它看起来不会像您期望的那样。 PixelTest 通过在验证快照测试视图时预先强制布局视图来做到这一点。

您也可以使用 UIGraphicsImageRenderer 来完成此操作。

extension UIView {

    func image() -> UIImage {
        let imageRenderer = UIGraphicsImageRenderer(bounds: bounds)
        if let format = imageRenderer.format as? UIGraphicsImageRendererFormat {
            format.opaque = true
        }
        let image = imageRenderer.image { context in
            return layer.render(in: context.cgContext)
        }
        return image
    }

}