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

佐手、 提交于 2020-08-10 02:50:03

问题


I have found numerous examples of converting UIView to UIImage, and they work perfectly for once the view has been laid out etc. Even in my view controller with many rows, some of which are net yet displaying on the screen, I can do the conversion. Unfortunately, for some of the views that are too far down in the table (and hence have not yet been "drawn"), doing the conversion produces a blank UIImage.

I've tried calling setNeedsDisplay and layoutIfNeeded, but these don't work. I've even tried to automatically scroll through the table, but perhaps I'm not doing in a way (using threads) that ensures that the scroll happens first, allowing the views to update, before the conversion takes place. I suspect this can't be done because I have found various questions asking this, and none have found a solution. Alternatively, can I just redraw my entire view in a UIImage, not requiring a UIView?

From Paul Hudson's website

Using any UIView that is not showing on the screen (say a row in a UITableview that is way down below the bottom of the screen.

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

回答1:


You don't have to have a view in a window/on-screen to be able to render it into an image. I've done exactly this in 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
    }

}

This will render a view's layer into an image as it currently looks if it was to be rendered on-screen. That is to say, if the view hasn't been laid out yet, then it won't look the way you expect. PixelTest does this by force-laying out the view beforehand when verifying a view for snapshot testing.




回答2:


You can also accomplish this using 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
    }

}


来源:https://stackoverflow.com/questions/54691034/can-you-convert-uiview-that-is-not-currently-being-displayed-to-uiimage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!